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

Dragging not working using SSR after refresh

Open tettoffensive opened this issue 4 years ago β€’ 28 comments

I'm experiencing the issues mentioned in this issue. For some reason, it was closed, even though the issue isn't resolved. However, unlike the reporter in this issue, I am using the suggested _document.js API.

https://github.com/atlassian/react-beautiful-dnd/issues/1775#issuecomment-636077095

Expected behavior

react-beautiful-dnd should run without warnings and errors when using SSR with next.js production AND dev. I should be able to always pick up draggable items.

Actual behavior

Receiving the following errors when trying to run react-beautiful-dnd with next.js:

react-beautiful-dnd

Unable to find any drag handles in the context "0"

πŸ‘·β€ This is a development only message. It will be removed in production builds. react-beautiful-dnd.esm.js:39 react-beautiful-dnd

A setup problem was encountered.

Invariant failed: Draggable[id: id-0}]: Unable to find drag handle

πŸ‘·β€ This is a development only message. It will be removed in production builds. react-beautiful-dnd.esm.js:39 react-beautiful-dnd

Unable to find any drag handles in the context "0"

πŸ‘·β€ This is a development only message. It will be removed in production builds.

Which according to other issues should resolve the problem with the client, server id mismatches when using SSR. But it's not resolved for me sadly.

The issue appears to be most reproduceable, by refreshing the page after initial load in development mode.

Steps to reproduce

Install the next.js, react-beautiful-react-dnd Follow this tutorial: https://egghead.io/courses/beautiful-and-accessible-drag-and-drop-with-react-beautiful-dnd

In this tutorial the attribute innerRef is being used. Don't use it. Instead use the ref attribute!

What version of react-beautiful-dnd and react are you running?

I'm using the following dependencies (listed in my package.json file):

"react": "^16.13.1",
"react-beautiful-dnd": "^13.0.0",
Next.js v9.4.0

What browser are you using?

Chrome Version 83.0.4103.61 (Official Build) (64-bit) Firefox 76.0.1 (64-bit)

tettoffensive avatar Jun 02 '20 05:06 tettoffensive

I'm facing this exact issue. I'm also using nextjs and SSR

react-beautiful-dndA setup problem was encountered.> Invariant failed: Draggable[id: ostKJgjkAzaeOBWowkz9]: Unable to find drag handleπŸ‘·β€ This is a development only message. It will be removed in production builds. at Draggable (http://localhost:3000/_next/static/development/pages/dashboard.js?ts=1592266231892:92012:65) at ConnectFunction (http://localhost:3000/_next/static/development/pages/dashboard.js?ts=1592266231892:108095:75) at PrivateDraggable (http://localhost:3000/_next/static/development/pages/dashboard.js?ts=1592266231892:92364:26) at PublicDraggable (http://localhost:3000/_next/static/development/pages/dashboard.js?ts=1592266231892:92374:32) at div at Droppable (http://localhost:3000/_next/static/development/pages/dashboard.js?ts=1592266231892:92386:76) at ConnectFunction (http://localhost:3000/_next/static/development/pages/dashboard.js?ts=1592266231892:108095:75) at Provider (http://localhost:3000/_next/static/development/pages/dashboard.js?ts=1592266231892:107808:20) at App (http://localhost:3000/_next/static/development/pages/dashboard.js?ts=1592266231892:90983:25) at ErrorBoundary (http://localhost:3000/_next/static/development/pages/dashboard.js?ts=1592266231892:84248:35) at DragDropContext (http://localhost:3000/_next/static/development/pages/dashboard.js?ts=1592266231892:91112:19) at div at div at http://localhost:3000/_next/static/development/pages/dashboard.js?ts=1592266231892:95916:23 at div at div at http://localhost:3000/_next/static/development/pages/dashboard.js?ts=1592266231892:93645:23 at div at http://localhost:3000/_next/static/development/pages/dashboard.js?ts=1592266231892:94302:23 at div at http://localhost:3000/_next/static/development/pages/dashboard.js?ts=1592266231892:98297:23 at div at TasksInfo (http://localhost:3000/_next/static/development/pages/dashboard.js?ts=1592266231892:1040:80) at div at div at http://localhost:3000/_next/static/development/pages/dashboard.js?ts=1592266231892:94302:23 at div at http://localhost:3000/_next/static/development/pages/dashboard.js?ts=1592266231892:98297:23 at div at http://localhost:3000/_next/static/development/pages/dashboard.js?ts=1592266231892:94525:23 at div at Dashboard (http://localhost:3000/_next/static/development/pages/dashboard.js?ts=1592266231892:112708:22) at MyApp (http://localhost:3000/_next/static/development/pages/_app.js?ts=1592266231892:4225:24) at Container (http://localhost:3000/_next/static/runtime/main.js?ts=1592266231892:2829:5) at AppContainer (http://localhost:3000/_next/static/runtime/main.js?ts=1592266231892:3245:24)

dhruvbhatia7 avatar Jun 16 '20 00:06 dhruvbhatia7

also using nextJS facing this. but I did not use SSR

image

Can be easily reproduce with any sample codes.

Apparently linked to this https://github.com/atlassian/react-beautiful-dnd/issues/1883 . It can be used after npm run build but not when in hot reload environment

daveteu avatar Jul 01 '20 10:07 daveteu

Guys, try to make this in _document.js:

import { resetServerContext } from 'react-beautiful-dnd'
...
static getInitialProps({ renderPage }) {
    resetServerContext()
}
...
render () { ...

denieler avatar Jul 26 '20 09:07 denieler

Guys, try to make this in _document.js:


import { resetServerContext } from 'react-beautiful-dnd'

...

static getInitialProps({ renderPage }) {

    resetServerContext()

}

...

render () { ...

This worked for me

0thernet avatar Aug 02 '20 21:08 0thernet

Guys, try to make this in _document.js:

import { resetServerContext } from 'react-beautiful-dnd'
...
static getInitialProps({ renderPage }) {
    resetServerContext()
}
...
render () { ...

Something change, now the bug is another...

image

May be do you have any clue?

MacGyver98 avatar Sep 14 '20 14:09 MacGyver98

Guys, try to make this in _document.js:

import { resetServerContext } from 'react-beautiful-dnd'
...
static getInitialProps({ renderPage }) {
    resetServerContext()
}
...
render () { ...

Sorry, my mistake. It works !!! I was using Draggable in wrong way... Gracias compadre! (as we say in my country)

MacGyver98 avatar Sep 14 '20 16:09 MacGyver98

Another solution was to use the react-no-ssr library. Just wrap the whole DND component with <NoSSR>.

<NoSSR>
   ... // react-beautiful-dnd code inside
</NoSSR>

dimitrisraptis96 avatar Dec 08 '20 16:12 dimitrisraptis96

Another solution was to use the react-no-ssr library. Just wrap the whole DND component with <NoSSR>.

<NoSSR>
   ... // react-beautiful-dnd code inside
</NoSSR>

This worked! Thanks

hopetambala avatar Jan 16 '21 14:01 hopetambala

getInitialProps is deprecated, I would recommend using getServerSideProps to fix this issue.

Here is how to do it with Typescript:

import { GetServerSideProps } from "next";
import { resetServerContext } from "react-beautiful-dnd";

export const getServerSideProps: GetServerSideProps = async (context) => {
  resetServerContext();
  return { props: {} };
};

lopezjurip avatar Jan 31 '21 19:01 lopezjurip

Another solution:

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

useEffect(() => {
  setCanRender(process.browser);
}, [])

function Home() {
  return(
   <>
    {isBrowser ? <DragDropContext> { /* all rbd code */ } </DragDropContext> : null}
   </>
  )
}

ivorpad avatar Mar 03 '21 07:03 ivorpad

This worked for me: image

IKrehan avatar Apr 04 '21 04:04 IKrehan

@IKrehan solution is not really correct as resetServerContext should run on the server. But I guess it works on the client if you only use one DragDropContext. The problem is that with up-to-date Next.js (v10.2.x) it does not work anymore when resetServerContext is called in getInitialProps or getServerSideProps (react-dom.development.js:66 Warning: Prop data-rbd-draggable-context-id did not match. Server: "0" Client: "1"). I will investigate a bit further.

medihack avatar May 21 '21 06:05 medihack

After some investigation and looking at the code it seems the root of the problem is more the client-side than the server-side. resetServerContext resets the context id correctly each time (that's why Server: "0" is logged). But in strict mode (I have it enabled as recommended by the Next.js team the client code is rendered twice. This is why the id ends up as 1 (Client: "1") instead of 0 (even I only have one DragDropContext. Can anyone confirm that React strict mode is enabled in his setup, too?

A possible workaround (just tested quickly) is to directly call resetServerContext in the render method of every page component which uses react-beautiful-dnd. That way the context id is reset on the server and client and always begins with 0. Not sure if there are any drawbacks.

medihack avatar May 21 '21 18:05 medihack

The react-no-ssr component worked for me, but I would like to know why resetServerContext doesn't work as expected

uncvrd avatar Jul 07 '21 06:07 uncvrd

If you guys want to use react-beautiful-dnd with Next.js, this is my solution, i just make a component contain dnd not work with SSR of Next and it's work for me.

// your route (like dashboard/index.js)

import dynamic from 'next/dynamic';

const Your_Component_Name = dynamic(() => import('your_patch_of_component'), {
  ssr: false,
});

export default function App() {
 return (
   <Your_Component_Name />
)
}

I done my dnd followed by this tutorial: https://www.freecodecamp.org/news/how-to-add-drag-and-drop-in-react-with-react-beautiful-dnd/

trinhphuocbinh1993 avatar Jul 30 '21 10:07 trinhphuocbinh1993

Also if you don't need HTML5 DND support then dnd-kit is a very good other solution with Next.js support I am quite happy with (very actively developed).

medihack avatar Jul 30 '21 12:07 medihack

If you guys want to use react-beautiful-dnd with Next.js, this is my solution, i just make a component contain dnd not work with SSR of Next and it's work for me.

// your route (like dashboard/index.js)

import dynamic from 'next/dynamic';

const Your_Component_Name = dynamic(() => import('your_patch_of_component'), {
  ssr: false,
});

export default function App() {
 return (
   <Your_Component_Name />
)
}

I done my dnd followed by this tutorial: https://www.freecodecamp.org/news/how-to-add-drag-and-drop-in-react-with-react-beautiful-dnd/

This works perfectly, thanks for the solution.

dhruvindsd-dev avatar Jul 30 '21 12:07 dhruvindsd-dev

If anyone still looking for SSR NextJS solution, following way of importing worked

import dynamic from 'next/dynamic';
const DragDropContext = dynamic(
  () =>
    import('react-beautiful-dnd').then(mod => {
      return mod.DragDropContext;
    }),
  {ssr: false},
);
const Droppable = dynamic(
  () =>
    import('react-beautiful-dnd').then(mod => {
      return mod.Droppable;
    }),
  {ssr: false},
);
const Draggable = dynamic(
  () =>
    import('react-beautiful-dnd').then(mod => {
      return mod.Draggable;
    }),
  {ssr: false},
);

sharva avatar Oct 03 '21 03:10 sharva

If anyone still looking for SSR NextJS solution, following way of importing worked

import dynamic from 'next/dynamic';
const DragDropContext = dynamic(
  () =>
    import('react-beautiful-dnd').then(mod => {
      return mod.DragDropContext;
    }),
  {ssr: false},
);
const Droppable = dynamic(
  () =>
    import('react-beautiful-dnd').then(mod => {
      return mod.Droppable;
    }),
  {ssr: false},
);
const Draggable = dynamic(
  () =>
    import('react-beautiful-dnd').then(mod => {
      return mod.Draggable;
    }),
  {ssr: false},
);

Thanks so much, this worked for me instantly :)

WaleedAmer avatar Oct 23 '21 05:10 WaleedAmer

Guys, try to make this in _document.js:

import { resetServerContext } from 'react-beautiful-dnd'
...
static getInitialProps({ renderPage }) {
    resetServerContext()
}
...
render () { ...

so do I create _document.js and then copy this code or what?

gx2475 avatar Oct 30 '21 03:10 gx2475

getInitialProps is obsolete and should not be used, use getServerSideProps instead.

resetServerContext() does not work in many cases. There is still no official solution.

Would be great to have the SSR logic inside DragDropContext.

codelover2k avatar Nov 14 '21 17:11 codelover2k

Any update on this ????

asenseofpradhyu avatar Jan 09 '22 08:01 asenseofpradhyu

If anyone still looking for SSR NextJS solution, following way of importing worked

import dynamic from 'next/dynamic';
const DragDropContext = dynamic(
  () =>
    import('react-beautiful-dnd').then(mod => {
      return mod.DragDropContext;
    }),
  {ssr: false},
);
const Droppable = dynamic(
  () =>
    import('react-beautiful-dnd').then(mod => {
      return mod.Droppable;
    }),
  {ssr: false},
);
const Draggable = dynamic(
  () =>
    import('react-beautiful-dnd').then(mod => {
      return mod.Draggable;
    }),
  {ssr: false},
);

Thanks so much, this worked for me instantly :)

This worked well for me!

planktonrobo avatar Feb 06 '22 00:02 planktonrobo

If anyone still looking for SSR NextJS solution, following way of importing worked

import dynamic from 'next/dynamic';
const DragDropContext = dynamic(
  () =>
    import('react-beautiful-dnd').then(mod => {
      return mod.DragDropContext;
    }),
  {ssr: false},
);
const Droppable = dynamic(
  () =>
    import('react-beautiful-dnd').then(mod => {
      return mod.Droppable;
    }),
  {ssr: false},
);
const Draggable = dynamic(
  () =>
    import('react-beautiful-dnd').then(mod => {
      return mod.Draggable;
    }),
  {ssr: false},
);

Thank you so much.

nirajpdn avatar Apr 27 '22 12:04 nirajpdn

If anyone still looking for SSR NextJS solution, following way of importing worked

import dynamic from 'next/dynamic';
const DragDropContext = dynamic(
  () =>
    import('react-beautiful-dnd').then(mod => {
      return mod.DragDropContext;
    }),
  {ssr: false},
);
const Droppable = dynamic(
  () =>
    import('react-beautiful-dnd').then(mod => {
      return mod.Droppable;
    }),
  {ssr: false},
);
const Draggable = dynamic(
  () =>
    import('react-beautiful-dnd').then(mod => {
      return mod.Draggable;
    }),
  {ssr: false},
);

If anyone, like me, is using Typescript and getting errors with the above try this:

import dynamic from 'next/dynamic';

const DragDropContext = dynamic(
  async () => {
    const mod = await import('react-beautiful-dnd');
    return mod.DragDropContext;
  },
  { ssr: false },
);

const Droppable = dynamic(
  async () => {
    const mod = await import('react-beautiful-dnd');
    return mod.Droppable;
  },
  { ssr: false },
);
const Draggable = dynamic(
  async () => {
    const mod = await import('react-beautiful-dnd');
    return mod.Draggable;
  },
  { ssr: false },
);

tettoffensive avatar Apr 27 '22 18:04 tettoffensive

somebody made it work with next13 + app directory? mixed server and client components with 'use client'; directive

masterkain avatar Apr 20 '23 23:04 masterkain

What about Nextjs 13.4.4 + App Directory . Im having this Issue . please help

shrix1 avatar Jun 16 '23 11:06 shrix1

If anyone still looking for SSR NextJS solution, following way of importing worked

import dynamic from 'next/dynamic';
const DragDropContext = dynamic(
  () =>
    import('react-beautiful-dnd').then(mod => {
      return mod.DragDropContext;
    }),
  {ssr: false},
);
const Droppable = dynamic(
  () =>
    import('react-beautiful-dnd').then(mod => {
      return mod.Droppable;
    }),
  {ssr: false},
);
const Draggable = dynamic(
  () =>
    import('react-beautiful-dnd').then(mod => {
      return mod.Draggable;
    }),
  {ssr: false},
);

thx!

SemX74 avatar Sep 23 '23 16:09 SemX74