react-querybuilder: NextJS ES Module build fails because of react-dnd

It all works fine with the barebone React app although fails with the NEXT.JS app. Works with version 4.2.3 where it uses an older version of react-dnd: react-dnd "^14.0.4" react-dnd-html5-backend "^14.0.2"

Please take a look at this sandbox. https://codesandbox.io/s/next-querybuilder-pj1d4s

Error msg: image

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 2
  • Comments: 21 (13 by maintainers)

Most upvoted comments

All - I just merged #343 after confirming that it works with NextJS where v4.5.2 fails. Thanks for all your help!

I’m going to release v5.0 soon (maybe as a beta first to be careful), but I have one more major decision to make: should we go ESM-only? I’m not aware of any problems the current build setup is causing (outside of this issue, which is resolved of course), but it seems right to embrace The Future™ anyway. If someone needs a CommonJS or UMD version they can always stay on v4, which isn’t really that different from v5 in terms of functionality at this point. Anyone have any opinions on it?

Gah! That makes so much sense!

Thanks so much for the excellent feedback. I wasn’t even considering the possibility of other enhancement/augmentation/wrapper packages, but now that seems like the obvious path forward. (Can’t wait to see what @react-querybuilder/cool-locale-stuff does! 😉 )

I’ll refactor the PR to support composition and start prepping for v5!

Hey Jake! Thanks for the work on this one, especially in summer 🌴. I’m exited to use it in NextJS!

I just wanted to give my opinion. I like option 2, because it extends the current QueryBuilder instead of replacing it with another instance of another package. This adds a bit more “boilerplate” code to it, but I think when it’s written like that, it’s easier to understand. I dont use “another” QueryBuilder, I use the same one, enable it’s internal drag-and-drop functionality by setting the enableDragAndDrop prop and wrap it in a DnD context. Maybe your just written DnD-context, maybe a context I customized myself, its extendable.

I think this will allow for easier customization and extension in the future. Imagine another wrapper package for a new dnd-library or a QueryBuilderLocaleProvider/QueryBuilderDateFns something like that. With option 2 I could just add or remove wrappers around the QueryBuilder. With option 1 I can only use 1 library, because im using that one’s whole QueryBuilder.

Option 1

import { QueryBuilder } from '@react-querybuilder/dnd';

<QueryBuilder enableDragAndDrop enableLocaleProvider /> // enableLocaleProvider functionality needs to be in dnd package, because I use it's QueryBuilder

Option 2

import { QueryBuilderLocaleProvider} from '@react-querybuilder/cool-locale-stuff';
import { QueryBuilderDnD } from '@react-querybuilder/dnd';
import { QueryBuilder } from 'react-querybuilder';

<QueryBuilderLocaleProvider>
    <QueryBuilderDnD>
        <QueryBuilder enableDragAndDrop />
    </QueryBuilderDnD>
</QueryBuilderLocaleProvider>

I hope you can understand what I mean : ) I’m no professional in writing libraries, just wanted to share. Whatever it will be, both options are alright. Have a nice day! : )

Ok I think I finally have #343 done. It extracts all drag-and-drop code into a separate package called @react-querybuilder/dnd, so using react-querybuilder v5 by itself should avoid any react-dnd-related problems (as it pertains to this library). It also makes the react-dnd dependency dynamic so you can use any version >=14.

Currently the new package exports a drop-in replacement for <QueryBuilder /> that includes drag-and-drop functionality. But I realized last night that it could have used composition instead.

I need to make a choice between the following two upgrade paths from v4 to v5.

(Note: These changes will only apply if enableDragAndDrop is true - otherwise the upgrade won’t require any code changes. When applicable, both options will require users to manually add react-dnd and react-dnd-html5-backend since they will be peerDependencies of @react-querybuilder/dnd.)

Option 1 (current design)

-import { QueryBuilder } from 'react-querybuilder';
+import { QueryBuilder } from '@react-querybuilder/dnd';

 export const App = () => {
   return (
     <QueryBuilder enableDragAndDrop />
   )
 }

Option 2

+import { QueryBuilderDnD } from '@react-querybuilder/dnd';
 import { QueryBuilder } from 'react-querybuilder';

 export const App = () => {
   return (
-    <QueryBuilder enableDragAndDrop />
+    <QueryBuilderDnD>
+      <QueryBuilder enableDragAndDrop />
+    </QueryBuilderDnD>
   )
 }

Option 2 would simplify @react-querybuilder/dnd’s code a bit, but it’s slightly more work for the users.

Any opinions on which way is better? I could design it to allow either method, but that wouldn’t help with simplifying this library’s code like if I chose option 2 by itself. (The code simplification isn’t super important since the more complex version is already written, after all.)

No hurt feelings! And no need to apologize. I just wanted to be open about the reality of the situation. I appreciate your kind words about RQB.

Thanks, @mohsinamjad.

I might try moving react-dnd (and react-dnd-html5-backend) to devDependencies and peerDependencies, using peerDependenciesMeta to make them optional for consuming applications. Then we’d just have to figure out how to detect them and fall back to enableDragAndDrop={false} (with a dev-only console warning) when they’re not available. This also probably means we’ll have to bite the bullet and go ESM-only.