React-beautiful-dnd: Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format.

Created on 15 Apr 2019  路  18Comments  路  Source: atlassian/react-beautiful-dnd

Expected behavior

I would expect there to be no warning. I may be missing a step to get this to work correctly.

Actual behavior

Gives "Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format."

Steps to reproduce

Use the library with Next.js

Suggested solution?

Is there a way to fix/silence the warnings?

What version of React are you using?

16.8.5

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

11.0.0

What browser are you using?

Chrome

Demo

more information required

Most helpful comment

For those who run into this problem with next and react-apollo:

With the next-with-apollo package I experienced this issue but then I refactored my apollo client initialization based on the official Next.js repo:

https://github.com/zeit/next.js/tree/canary/examples/with-apollo

Now it works perfectly without throwing the warning messages.

All 18 comments

Interesting. We currently do a lame hack to get around useLayoutEffect SSR warnings.

I suspect that next.js is setting up a window 馃

We avoid using useLayoutEffect in node environments for this reason. However, it looks like something going on in next might be circumventing our logic.

I have tested next and I cannot reproduce the issue. I even checked a production build

https://github.com/alexreardon/nextjs-rbd

I'm experiencing this though I think it's a result of an unrelated problem to react-beautiful-dnd.

In our case, the warning appears when changing pages, but not on the server-side render. This initially sounds really weird (why is there a SSR warning on a client render?).

The answer lies in the fact that we're using react-apollo alongside next.js.

Page changes cause getDataFromTree from react-apollo to run, which calls:

require("react-dom/server").renderToStaticMarkup

So even though the rendering is running on the client, it runs a "server" render, which I think results in the warning.

Though of course this doesn't explain any behaviour that isn't linked to react-apollo (not sure what @ElektrikSpark's setup is!) 馃檪

I'll close this for now. Please let me know if you think there is anything we should be doing

Just pitching in that I'm experiencing the same console error. Like @benhjames, I'm using NextJS and react-apollo and the error triggers on page change.

Only thought to look in this repo as the stack trace points be to the Draggable component

image

Wish I could contribute more to the conversation :S

I am using Next.js and react-apollo/react-apollo-hooks as well. Guess I just didn't notice the error until I implemented react-beautiful-dnd?

it looks like our useLayoutEffect / useLayout SSR swap logic is not working in react-apollo. Have you come across this @markerikson?

Per that comment earlier, it sounds as if they're using ReactDOMServer.renderToStarticMarkup() on the client side (which I've seen done a few times). That SSR implementation is what contains the useLayoutEffect warning. It would normally be running under Node, in which case the "does window exist" check be false and fall back to useEffect. But, since this is A) SSR code that warns, and B) running in a browser environment where window _does_ exist, you end up with an actual attempt to call useLayoutEffect, which ends up warning.

Aye. Thanks @markerikson. It is painful that useLayoutEffect logs an SSR warning..

https://github.com/facebook/react/issues/14927

For those who run into this problem with next and react-apollo:

With the next-with-apollo package I experienced this issue but then I refactored my apollo client initialization based on the official Next.js repo:

https://github.com/zeit/next.js/tree/canary/examples/with-apollo

Now it works perfectly without throwing the warning messages.

Thank you @akosbeke for your solution with the apollo config, it is fixing the "useLayoutEffect" error message.
But, there is still a problem which persists on the first render of a React Beautiful DnD component, which displays the following error message for each draggable element:

"react-beautiful-dnd A setup problem was encountered.> Invariant failed: Draggable[id: item-0]: Unable to find drag handle"

To reproduce this bug I've created the following repo:
https://github.com/TLevesque/Nextjs-Apollo-React-Beautiful-DnD
which is just the combination of your repo from Nextjs examples with the apollo config and Nextjs
https://github.com/zeit/next.js/tree/canary/examples/api-routes-apollo-server-and-client and the one of @alexreardon
https://github.com/alexreardon/nextjs-rbd he has made for a test with Nextjs.

I've modified nothing into the code of each repository, just imported the Alex' component into nextjs example repo.
Apparently, switching from dynamic page to static, make the DnD elements working again, but I've no clue about how to make it work on the first render, any idea?

Thanks

Let me know if you want any input @akosbeke. Here is how we are getting around the issue: https://medium.com/@alexandereardon/uselayouteffect-and-ssr-192986cdcf7a

Hey @TLevesque,

Well I've spent some time with your example repo and I spotted that there are version differences in the package.json files.

In theory you shouldn't occur any problems due to thereact-apollo integration since your /about page does not use the withApollo HOC.

I went ahead and changed the package.json file of the /alexreardon/nextjs-rbd repo and updated the react-beautiful-dnd package to 12.1.1 (like in your example) and it started to show the same error at first renders (which is SSR). Also your test repo should work with version ^11.0.0 of react-beautiful-dnd.

At this point I have no idea what causes the error but I am pretty sure it has nothing to do with react-apollo. Looks like the bug has been introduced with some of the updates of the react-beautiful-dnd package and it is related to NextJS or SSR in general somehow.

@alexreardon does this - by any chance - ring a bell?

It might not be related but there is a warning message as well about the server and client context IDs being different. And the server context id is increased by one with every hard page refresh (the client id always remains "0").

Warning: Propdata-rbd-draggable-context-iddid not match. Server: "2" Client: "0"

Using Next.js with rb-dnd. On inital page load i.e. server rendered, i get:

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

It's then unresponsive

However if navigation to the page that uses it ,i.e. client rendered, it works as expected, any idea?

@akosbeke

It might not be related but there is a warning message as well about the server and client context IDs being different. And the server context id is increased by one with every hard page refresh (the client id always remains "0").

Warning: Propdata-rbd-draggable-context-iddid not match. Server: "2" Client: "0"

I don't think it's related at all to the current issue. However, I found this thread trying to find a solution to the warning 馃檲 , so, according to this: https://github.com/atlassian/react-beautiful-dnd/blob/master/docs/api/reset-server-context.md

I solved it by adding resetServerContext() in pages/_document.tsx

@eddyw where exactly did you include it in your pages/_document.tsx? I added it but still get:

"Warning: Prop data-react-beautiful-dnd-draggable did not match. Server: "7" Client: "0"

// ...
import { resetServerContext } from 'react-beautiful-dnd';

resetServerContext();

export default class MyDocument extends Document {
// ...

update: this is how it is supposed to be done https://github.com/atlassian/react-beautiful-dnd/issues/436

If you are still having this issue and you are using a package that has react-beautiful-dnd as a dependency, you are probably resetting the server context on the wrong module instance.

@kyle-mccarthy yeah, my solution was similar. If you actually need to overwrite the ctx.renderPage, then you can also put it there. Otherwise just keep it simple:

CustomDocument.getInitialProps = async (ctx) => {
  resetServerContext()
  return Document.getInitialProps(ctx)
}
Was this page helpful?
0 / 5 - 0 ratings