-
-
Notifications
You must be signed in to change notification settings - Fork 32.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Warning: useLayoutEffect does nothing on the server, because its effect cannot […] #15798
Comments
This means your test setup has a DOM while you're using sever-side rendering. I don't think ReactDOM.renderToStaticMarkup has use cases in the browser. I believe you can tell jest to run tests in a specific environment. For your SSR tests you should run in Edit by @oliviertassinari Would it work, in your case with? (from react): // React currently throws a warning when using useLayoutEffect on the server.
// To get around it, we can conditionally useEffect on the server (no-op) and
// useLayoutEffect in the browser.
const canUseDOM: boolean = !!(
typeof window !== 'undefined' &&
typeof window.document !== 'undefined' &&
typeof window.document.createElement !== 'undefined'
);
const useIsomorphicLayoutEffect = canUseDOM ? useLayoutEffect : useEffect; |
I'm using Next.js and I'm getting the same alert but in Chrome Console when my pages loads. |
Creating a fresh copy of our example does not log any warnings for me. If you have some custom setup please include a complete reproducible example. The same applies to @TidyIQ. The issue depends on your specific environment. I would guess that you get the same warnings using the latest version of react-redux. |
My code is quite large so it will take a bit of time to provide a reproduction, but just to confirm I'm also use Next.js and my tests are being run in jsdom (with jest and react-testing-library), puppeteer (with jsdom-screenshot) and ReactDOM.renderToStaticMarkup (with jest-axe). I haven't yet determined which are causing the issue yet. |
That is the issue. You're creating an environment that is quite different from your production environment. On the server you won't have a DOM available. For tests using |
@eps1lon I found the source of issue in my case.
When I click in any of this links, the new page is loaded and the warnings are shown at DevTools Just changing the import to |
FINALLY, I could reproduce the error! 😅 If I use the example for Next and Apollo (https://github.com/zeit/next.js/tree/master/examples/with-apollo) the problem do not occur but I lost some good functionalities tha Steps to do it: Clone the example of MUI with NextJS (https://github.com/mui-org/material-ui/tree/master/examples/nextjs)
Create the HOC that create an Apollo Client (next-with-apollo.js)
Attach the HOC on _app.js
Add some Button to any page!
|
That must be it. I'm also using Apollo Client. |
Thanks for the repro. Will check if this still happens using reduxjs/react-redux#1283. |
@ralvs Repro doesn't start. Could you create a cloneable repository or checkout https://github.com/eps1lon/mui-buttonbase-uselayout-repro and see what's missing? Followed your steps (replaced npm with yarn though). Had to install react-apollo (cannot find module) after that I get |
@eps1lon If I'm not mistaken, you ran into the following issue: apollographql/apollo-client#4843 Current workaround seems to be reverting to v0.3.1 or impor the client from apollo-boost/lib/index Thanks for working on this:-) |
@pedela Thanks for the tip. Can make it work: $ git clone https://github.com/eps1lon/mui-buttonbase-uselayout-repro.git
$ cd mui-buttonbase-uselayout-repro
$ yarn
$ yarn dev
# goto localhost:3000/about but I can't reproduce any error. Neither browser nor terminal console log any warnings related to |
I also open a issue on |
Can anbody reproduce this on a linux distribution? Maybe apollo is mocking some part of the DOM on the server on mac only? |
I can reproduce this exact error on an Ubuntu-based distribution. |
I can reproduce on MacOS 10.14.5. |
Ok found it. We can close this issue. You can reproduce the problem without Material-UI: import React from "react";
const useEnhancedEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
function MadeWithLove() {
useEnhancedEffect(() => {});
return (
<span>
{"Built with love by the "}
</span>
);
} The problem is that
I have used Apollo extensively for more than a year at onepixel.com. I would be cautious with it, it can be slow at scale, it was our bottleneck n°1 from a performance perspective (graphql + apollo client). I believe you don't need to traverse the React tree with the server side API on the client when switching routes. You can have loaders or a centralized getInitialProps logic instead. |
I'm happy to have found the existence of ua-parser-js. I will update the ssr documentation of useMediaQuery with it, it can help when client hints are not available. |
I agree with you, and thanks for your help.
This took me a lot of time to find out that the reason for these warnings is that the material-ui does not correctly recognize is this server or client. And it is based on the presence of the window object |
@ndeviant Do we have a better option? |
This comment has been minimized.
This comment has been minimized.
@ndeviant Sorry, this was an invitation to read the whole thread. @eps1lon has already suggested a great possible approach in #15798 (comment). Would it work, in your case with? (from react): // React currently throws a warning when using useLayoutEffect on the server.
// To get around it, we can conditionally useEffect on the server (no-op) and
// useLayoutEffect in the browser.
const canUseDOM: boolean = !!(
typeof window !== 'undefined' &&
typeof window.document !== 'undefined' &&
typeof window.document.createElement !== 'undefined'
);
const useIsomorphicLayoutEffect = canUseDOM ? useLayoutEffect : useEffect; |
@eps1lon Should we reopen and deploy a Note that it's broader to the layout effect, we run a |
@oliviertassinari yeah, totally. Thats would be great! |
This comment has been minimized.
This comment has been minimized.
I described only one case when window on server could be useful. Initial issue creator has 9 "Thumbs up" on this, it seems like people keep running into this issue over and over again, with different circumstances (tests env, not ideal deps, etc.). My actual issue is, I've got the project, written before me, which uses window on server, and go and refactor everything that uses this logic, just to get rid of annoying warning I cannot afford. To conclude what I was saying previously:
React doesn't takes responsibility to say, that you shouldn't have defined 'window' on server, and checks properly for dom existence. |
It's something we can't control. Unfortunately we only have Now we solve this issue by assuming that the SSR api is used on the server and the CSR api is used on the client. But nothing prevents you from using the SSR api on the client as well (or rather in environments with a DOM) which results in these false positives. We voiced our concern about this warning to the react core team but didn't get any response. At this point we cannot do anything more. As far as I know there's no way of knowing if a component is rendered with the SSR api or CSR api. If there is then we could solve this issue. |
To the developers coming to this page. If you are affected by this problem, please upvote the issue and provide a reproduction we can look at. The more feedback, the best solution we can find. Thanks. |
Hello, I reproduced using Enzyme's render function. |
I have same problema, index.js:1 Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should only be used in components that render exclusively on the client. See https://fb.me/react-uselayouteffect-ssr for common fixes. Code. package: |
Still this error occurs with Internally Or use "useIsomorphicLayoutEffect"? I want to SSR with Material UI. If you have time, please check out the example which demonstrate this warnings: https://github.com/saltyshiomix/react-ssr/tree/master/examples/with-jsx-material-ui Dear, |
@saltyshiomix It seems that the warning comes from https://github.com/saltyshiomix/react-ssr/blob/50895251cb950cfa4ccccf03bff43011b4303e51/packages/core/lib/webpack/material-ui.js#L7. The usage of the server-side API on the client-side triggers these warnings. So, I would recommend not to two render twice on the client, for performance consideration. You will dodge the issue at the same time. Would that work for you? |
You are perfectly right, and solved the problem! I misunderstood the APIs, sorry. |
I have exactly the same issue. In fact, everybody using material-ui and next-with-apollo with the Using next-with-apollo with So if you could implement the "canUseDom" API it would be so great!! Moreover, the issue had been closed here and opened in the next-with-apollo package, but the maintainer of this package can do nothing because the issue is coming from Material UI. |
@lcswillems I would recommend I don't think that the proposal in #15798 (comment) will help your case. It's designed to people that have the issue when they render on the server and have a window that leaks, somewhere. In your case, I believe that it's when you render on the client. As far as I know, there is nothing we can do about it. We are constrained by React. |
Please see #15798 (comment) for why this is not possible for libraries. Or
|
Version 4 of
<ButtonBase>
now incorporatesuseLayoutEffect()
in the src code here. This wasn't present in version 3.I understand the need for it however every jest test for a component that has a
<Button>
within it now results in console warnings like so:The tests still pass as it's just a warning, but is there any way to prevent these warning messages from appearing? I literally can't even see all the warnings in my terminal as there are so many.
The text was updated successfully, but these errors were encountered: