react-beautiful-dnd icon indicating copy to clipboard operation
react-beautiful-dnd copied to clipboard

Not working with NextJS

Open mattiastofte opened this issue 2 years ago • 27 comments

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;

mattiastofte avatar Sep 15 '22 13:09 mattiastofte

yes, facing the same issue!

ketangupta34 avatar Sep 16 '22 15:09 ketangupta34

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

IgorSilvaZZ avatar Sep 16 '22 18:09 IgorSilvaZZ

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

ketangupta34 avatar Sep 17 '22 18:09 ketangupta34

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 avatar Sep 21 '22 07:09 fshahmt

#2092

zhatongning avatar Sep 21 '22 14:09 zhatongning

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

calin-borbeli avatar Oct 04 '22 09:10 calin-borbeli

Is anything logged to the console?

MikhailHusyev avatar Oct 17 '22 18:10 MikhailHusyev

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

mattiastofte avatar Oct 17 '22 20:10 mattiastofte

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 avatar Oct 17 '22 20:10 mattiastofte

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:)

mattiastofte avatar Oct 17 '22 20:10 mattiastofte

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.

MikhailHusyev avatar Oct 17 '22 23:10 MikhailHusyev

@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.

calin-borbeli avatar Oct 18 '22 08:10 calin-borbeli

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

JashandeepSinghGill avatar Nov 02 '22 05:11 JashandeepSinghGill

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

Mingyu-Song avatar Nov 06 '22 11:11 Mingyu-Song

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

guirip avatar Nov 15 '22 14:11 guirip

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

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

vincent38wargnier avatar Dec 02 '22 15:12 vincent38wargnier

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

ketangupta34 avatar Dec 11 '22 15:12 ketangupta34

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 }
);

kennethpole6 avatar Mar 07 '23 05:03 kennethpole6

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.

yatharth1706 avatar May 14 '23 13:05 yatharth1706

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.

kyle920326 avatar Jun 13 '23 08:06 kyle920326

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); };

Joyontokarmakar avatar Jul 08 '23 11:07 Joyontokarmakar

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

Nelio-Bila avatar Aug 12 '23 05:08 Nelio-Bila

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.

Clancy-Lewis avatar Jan 10 '24 05:01 Clancy-Lewis

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>

aymenkasP avatar Feb 03 '24 20:02 aymenkasP

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

aniketsingh98571 avatar Feb 23 '24 15:02 aniketsingh98571

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

dulranga avatar Apr 22 '24 06:04 dulranga

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!

jonathanroze avatar Jun 07 '24 07:06 jonathanroze