atlassian / react-beautiful-dnd

Beautiful and accessible drag and drop for lists with React
https://react-beautiful-dnd.netlify.app
Other
33.37k stars 2.56k forks source link

Not working with NextJS #2444

Open mattiastofte opened 2 years ago

mattiastofte commented 2 years ago

Hi. I'm having a quite difficult time utilising this library since it's not working at all in NextJS. I've tried coding it from scratch multiple times and looked trough the documentation extensively. I've also tried modifying my custom _document.tsx file with this change for SSR https://www.codedaily.io/tutorials/Using-react-beautiful-dnd-with-NextJS. I've tried the exact same code in CodePen and there it works.

Expected behavior

The ability to drag the elements.

Actual behavior

The cursor does not change to "grab" pointer and trying to drag the components does nothing. ezgif-4-0ba9444ee3

Versions and browser

React version: ^18.2.0 React-beautiful-dnd version: ^13.1.1 Browser: Chrome

Code (very simplified)

import type { NextPage } from 'next';
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';

const data = [
  {
    id: 'section-1',
    title: 'Section 1',
  },
  {
    id: 'section-2',
    title: 'Section 2',
  },
  {
    id: 'section-3',
    title: 'Section 3',
  },
];

const dnd: NextPage = () => {
  return (
    <DragDropContext>
      <Droppable droppableId="droppable">
        {(provided) => (
          <div {...provided.droppableProps} ref={provided.innerRef}>
            {data.map((item, index) => (
              <Draggable key={item.id} draggableId={item.id} index={index}>
                {(provided) => (
                  <div
                    ref={provided.innerRef}
                    {...provided.draggableProps}
                    {...provided.dragHandleProps}
                  >
                    {item.title}
                  </div>
                )}
              </Draggable>
            ))}
            {provided.placeholder}
          </div>
        )}
      </Droppable>
    </DragDropContext>
  );
};

export default dnd;
ketangupta34 commented 2 years ago

yes, facing the same issue!

IgorSilvaZZ commented 2 years ago

It's not a solution, but it solves the problem per hour after checking a lot I saw that it has an error in Next in the droppableId, so I created a variable that takes the current date and time, so I put it together with a variable. For me it just worked that way hope it helps in some way.

image

ketangupta34 commented 2 years ago

@IgorSilvaZZ Thanks for this, but apparently this didnt work for me. This issue still presists.

fshahmt commented 2 years ago

Hey everyone, I don't understand what the problem is here? I have a project in Next js and the last SDE implemented the dnd using the react dnd library but I have completely migrated to react beautiful dnd without any major hiccups. Maybe I can help out because I don't think it is a bug with the package.

Not sure that you're doing it the way I am because I didn't really care about the ssr part of it and just implemented it with the core functionality in react components (not an expert in next)

zhatongning commented 2 years ago

2092

calin-borbeli commented 2 years ago

Have you tried to set the ReactStrictMode: false in the next.config.js file?

MikhailHusyev commented 2 years ago

Is anything logged to the console?

mattiastofte commented 2 years ago

@calin-borbeli Yes, I've tried this and it didn't do anything sadly.

mattiastofte commented 2 years ago

Is anything logged to the console?

@MikhailHusyev after further inspection this does seem to be a duplicate of the same issue in #2092 although there doesn't seem to be any solutions here. I get the same error logged to my console.

mattiastofte commented 2 years ago

Hey everyone, I don't understand what the problem is here? I have a project in Next js and the last SDE implemented the dnd using the react dnd library but I have completely migrated to react beautiful dnd without any major hiccups. Maybe I can help out because I don't think it is a bug with the package.

Not sure that you're doing it the way I am because I didn't really care about the ssr part of it and just implemented it with the core functionality in react components (not an expert in next)

@fshahmt How did you get it working? Would it be possible have a call about this:)

MikhailHusyev commented 2 years ago

Is anything logged to the console?

@MikhailHusyev after further inspection this does seem to be a duplicate of the same issue in #2092 although there doesn't seem to be any solutions here. I get the same error logged to my console.

I was having the same issue, and I did find a solution for it.

import type { NextPage } from 'next';
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';

const [isBrowser, setIsBrowser] = useState(false);

useEffect(() => {
    if (typeof window !== "undefined") {
      setIsBrowser(true);
    }
  }, []);

const data = [
  {
    id: 'section-1',
    title: 'Section 1',
  },
  {
    id: 'section-2',
    title: 'Section 2',
  },
  {
    id: 'section-3',
    title: 'Section 3',
  },
];

const dnd: NextPage = () => {
  return (
    <DragDropContext>
<div>
{isBrowser ? (
      <Droppable droppableId="droppable">
        {(provided) => (
          <div {...provided.droppableProps} ref={provided.innerRef}>
            {data.map((item, index) => (
              <Draggable key={item.id} draggableId={item.id} index={index}>
                {(provided) => (
                  <div
                    ref={provided.innerRef}
                    {...provided.draggableProps}
                    {...provided.dragHandleProps}
                  >
                    {item.title}
                  </div>
                )}
              </Draggable>
            ))}
            {provided.placeholder}
          </div>
        )}
      </Droppable>
</div>
) : null}
    </DragDropContext>
  );
};

export default dnd;

I added a check to see if the rendering is on browser. The issue arises due to the fact that Next is rendering the page server side, so a check is required.

Checkout this repo: https://github.com/vunhutien/kanban-ui/blob/main/pages/index.js Also this project: https://github.com/zineb-Bou/Drag-drop-todo

If that doesn't work there are changes you can make within the _document.js that could resolve the issue.

calin-borbeli commented 2 years ago

@calin-borbeli Yes, I've tried this and it didn't do anything sadly.

@mattiastofte I didn't have time to test your code but here's a link to a simple working Next.js implementation https://github.com/calin-borbeli/Next-React-beautiful-dnd.git This is from the original course for React-beautiful-dnd created by Alex Reardon. It works with Next 12 and React 18 plus Typescript and Tailwind. I didn't need to do what has been suggested above. Have a look and see what is different. I can see a few differences but as I said I didn't test yours. I hope this helps.

JashandeepSinghGill commented 2 years ago

@MikhailHusyev thanks it worked for me what changed in that line I don't know, if you could explain that will be helpful Thanks

Mingyu-Song commented 2 years ago

and you don't need to check typeof window in useEffect https://github.com/vercel/next.js/discussions/17628

guirip commented 1 year ago

Thanks @calin-borbeli 🙏 Your link helped! ('First fix' in the README) https://github.com/calin-borbeli/Next-React-beautiful-dnd

vincent38wargnier commented 1 year ago

Hi, I found this solution: in next.config.js :

const nextConfig = {
  //  reactStrictMode: true, -- because of the 'bug' in react-beautiful-dnd
  swcMinify: true,
}
ketangupta34 commented 1 year ago

So the exact solution to make this work in next.js is to use

next.config.js

module.exports = {
  reactStrictMode: false,
  swcMinify: false,
};

and we need to convert from SSR to static

in the file where we load DragDropContext

  const [winReady, setwinReady] = useState(false);
  useEffect(() => {
    setwinReady(true);
  }, []);

With both, this added dnd will work

kennethpole6 commented 1 year ago

You can import the droppable with this. I works on my end with react-strict-mode enabled.

const Droppable = dynamic(
  () => import("react-beautiful-dnd").then((res) => res.Droppable),
  { ssr: false }
);
yatharth1706 commented 1 year ago

Is anything logged to the console?

@MikhailHusyev after further inspection this does seem to be a duplicate of the same issue in #2092 although there doesn't seem to be any solutions here. I get the same error logged to my console.

I was having the same issue, and I did find a solution for it.

import type { NextPage } from 'next';
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';

const [isBrowser, setIsBrowser] = useState(false);

useEffect(() => {
    if (typeof window !== "undefined") {
      setIsBrowser(true);
    }
  }, []);

const data = [
  {
    id: 'section-1',
    title: 'Section 1',
  },
  {
    id: 'section-2',
    title: 'Section 2',
  },
  {
    id: 'section-3',
    title: 'Section 3',
  },
];

const dnd: NextPage = () => {
  return (
    <DragDropContext>
<div>
{isBrowser ? (
      <Droppable droppableId="droppable">
        {(provided) => (
          <div {...provided.droppableProps} ref={provided.innerRef}>
            {data.map((item, index) => (
              <Draggable key={item.id} draggableId={item.id} index={index}>
                {(provided) => (
                  <div
                    ref={provided.innerRef}
                    {...provided.draggableProps}
                    {...provided.dragHandleProps}
                  >
                    {item.title}
                  </div>
                )}
              </Draggable>
            ))}
            {provided.placeholder}
          </div>
        )}
      </Droppable>
</div>
) : null}
    </DragDropContext>
  );
};

export default dnd;

I added a check to see if the rendering is on browser. The issue arises due to the fact that Next is rendering the page server side, so a check is required.

Checkout this repo: https://github.com/vunhutien/kanban-ui/blob/main/pages/index.js Also this project: https://github.com/zineb-Bou/Drag-drop-todo

If that doesn't work there are changes you can make within the _document.js that could resolve the issue.

I was stuck in this for like very long. This solution helped me thanks.

kyle920326 commented 1 year ago

I tried to solve this problem in NextJS , which was a different. used process.browser to judge isBrowser.


useEffect(() => {
    if (process.browser) {
      setIsBrowser(true);
    }
  }, []);

Is anything logged to the console?

@MikhailHusyev after further inspection this does seem to be a duplicate of the same issue in #2092 although there doesn't seem to be any solutions here. I get the same error logged to my console.

I was having the same issue, and I did find a solution for it.

import type { NextPage } from 'next';
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';

const [isBrowser, setIsBrowser] = useState(false);

useEffect(() => {
    if (typeof window !== "undefined") {
      setIsBrowser(true);
    }
  }, []);

const data = [
  {
    id: 'section-1',
    title: 'Section 1',
  },
  {
    id: 'section-2',
    title: 'Section 2',
  },
  {
    id: 'section-3',
    title: 'Section 3',
  },
];

const dnd: NextPage = () => {
  return (
    <DragDropContext>
<div>
{isBrowser ? (
      <Droppable droppableId="droppable">
        {(provided) => (
          <div {...provided.droppableProps} ref={provided.innerRef}>
            {data.map((item, index) => (
              <Draggable key={item.id} draggableId={item.id} index={index}>
                {(provided) => (
                  <div
                    ref={provided.innerRef}
                    {...provided.draggableProps}
                    {...provided.dragHandleProps}
                  >
                    {item.title}
                  </div>
                )}
              </Draggable>
            ))}
            {provided.placeholder}
          </div>
        )}
      </Droppable>
</div>
) : null}
    </DragDropContext>
  );
};

export default dnd;

I added a check to see if the rendering is on browser. The issue arises due to the fact that Next is rendering the page server side, so a check is required.

Checkout this repo: https://github.com/vunhutien/kanban-ui/blob/main/pages/index.js Also this project: https://github.com/zineb-Bou/Drag-drop-todo

If that doesn't work there are changes you can make within the _document.js that could resolve the issue.

Joyontokarmakar commented 1 year ago

Is anything logged to the console?

@MikhailHusyev after further inspection this does seem to be a duplicate of the same issue in #2092 although there doesn't seem to be any solutions here. I get the same error logged to my console.

I was having the same issue, and I did find a solution for it.

import type { NextPage } from 'next';
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';

const [isBrowser, setIsBrowser] = useState(false);

useEffect(() => {
    if (typeof window !== "undefined") {
      setIsBrowser(true);
    }
  }, []);

const data = [
  {
    id: 'section-1',
    title: 'Section 1',
  },
  {
    id: 'section-2',
    title: 'Section 2',
  },
  {
    id: 'section-3',
    title: 'Section 3',
  },
];

const dnd: NextPage = () => {
  return (
    <DragDropContext>
<div>
{isBrowser ? (
      <Droppable droppableId="droppable">
        {(provided) => (
          <div {...provided.droppableProps} ref={provided.innerRef}>
            {data.map((item, index) => (
              <Draggable key={item.id} draggableId={item.id} index={index}>
                {(provided) => (
                  <div
                    ref={provided.innerRef}
                    {...provided.draggableProps}
                    {...provided.dragHandleProps}
                  >
                    {item.title}
                  </div>
                )}
              </Draggable>
            ))}
            {provided.placeholder}
          </div>
        )}
      </Droppable>
</div>
) : null}
    </DragDropContext>
  );
};

export default dnd;

I added a check to see if the rendering is on browser. The issue arises due to the fact that Next is rendering the page server side, so a check is required.

Checkout this repo: https://github.com/vunhutien/kanban-ui/blob/main/pages/index.js Also this project: https://github.com/zineb-Bou/Drag-drop-todo

If that doesn't work there are changes you can make within the _document.js that could resolve the issue.

Thanks a lot to you for your Idea. It's working for me. But please note: provide handleDrop function in DragDropContext to keep your dragable iteme in next step. here is the example, "<DragDropContext onDragEnd={handleDrop}"

and the function is:

const handleDrop = (droppedItem) => { if (!droppedItem.destination) return; let updatedList = [...item]; const [reorderedItem] = updatedList.splice(droppedItem.source.index, 1); updatedList.splice(droppedItem.destination.index, 0, reorderedItem); setNavItem(updatedList); };

Nelio-Bila commented 1 year ago

It's not a solution, but it solves the problem per hour after checking a lot I saw that it has an error in Next in the droppableId, so I created a variable that takes the current date and time, so I put it together with a variable. For me it just worked that way hope it helps in some way.

image

This worked for me, uuids too can work

Clancy-Lewis commented 10 months ago

So the exact solution to make this work in next.js is to use

next.config.js

module.exports = {
  reactStrictMode: false,
  swcMinify: false,
};

and we need to convert from SSR to static

in the file where we load DragDropContext

  const [winReady, setwinReady] = useState(false);
  useEffect(() => {
    setwinReady(true);
  }, []);

With both, this added dnd will work

Worked for me.

aymenkasP commented 9 months ago

The { ...provided.dragHandleProps} is missing from the draggable component.

<Droppable droppableId={`${prefix}`}>
      {(provided) => (
        <div
          { ...provided.dragHandleProps} 
          {...provided.droppableProps}

          ref={provided.innerRef}
          className="p-3 grid gap-3 "
        >
          {elements?.map((item, index) => (
            <ListItem key={item.id} item={item} index={index} />
          ))}
          {provided.placeholder}
        </div>
      )}
    </Droppable>
aniketsingh98571 commented 8 months ago

Regarding this problem,even though I am using "use client" in the component,still DnD doesn't work, ultimately I had to check for browser rendering.

But still need reasoning of it being, not working

dulranga commented 6 months ago

making reactStrictMode: false in next.config.mjs solves the issue.

I get this warning before

app-index.js:33 Warning: Prop `data-rbd-draggable-context-id` did not match. Server: "1" Client: "0"
    at li
    at Draggable

Maybe the hydration failed. but this is a "use client" component

jonathanroze commented 5 months ago

Is anything logged to the console?

@MikhailHusyev after further inspection this does seem to be a duplicate of the same issue in #2092 although there doesn't seem to be any solutions here. I get the same error logged to my console.

I was having the same issue, and I did find a solution for it.

import type { NextPage } from 'next';
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';

const [isBrowser, setIsBrowser] = useState(false);

useEffect(() => {
    if (typeof window !== "undefined") {
      setIsBrowser(true);
    }
  }, []);

const data = [
  {
    id: 'section-1',
    title: 'Section 1',
  },
  {
    id: 'section-2',
    title: 'Section 2',
  },
  {
    id: 'section-3',
    title: 'Section 3',
  },
];

const dnd: NextPage = () => {
  return (
    <DragDropContext>
<div>
{isBrowser ? (
      <Droppable droppableId="droppable">
        {(provided) => (
          <div {...provided.droppableProps} ref={provided.innerRef}>
            {data.map((item, index) => (
              <Draggable key={item.id} draggableId={item.id} index={index}>
                {(provided) => (
                  <div
                    ref={provided.innerRef}
                    {...provided.draggableProps}
                    {...provided.dragHandleProps}
                  >
                    {item.title}
                  </div>
                )}
              </Draggable>
            ))}
            {provided.placeholder}
          </div>
        )}
      </Droppable>
</div>
) : null}
    </DragDropContext>
  );
};

export default dnd;

I added a check to see if the rendering is on browser. The issue arises due to the fact that Next is rendering the page server side, so a check is required.

Checkout this repo: https://github.com/vunhutien/kanban-ui/blob/main/pages/index.js Also this project: https://github.com/zineb-Bou/Drag-drop-todo

If that doesn't work there are changes you can make within the _document.js that could resolve the issue.

Thanks a lot, it's a working solution!