styled-components: Global styles does not work in React.StrictMode
Environment
System: OS: macOS 10.15.1 CPU: (8) x64 Intel® Core™ i7-8569U CPU @ 2.80GHz Memory: 857.00 MB / 16.00 GB Shell: 3.2.57 - /bin/bash Binaries: Node: 10.15.3 - ~/.nvm/versions/node/v10.15.3/bin/node Yarn: 1.16.0 - /usr/local/bin/yarn npm: 6.4.1 - ~/.nvm/versions/node/v10.15.3/bin/npm npmPackages: styled-components: ^5.0.1 => 5.0.1 Reproduction https://codesandbox.io/s/wonderful-hill-6glof
Steps to reproduce
Load the code sandbox Click the button “to black” and then click again “to white” and notice how the background did not change back to black.
Expected Behavior
The should change between black and white
Actual Behavior
The background stays black after the first press on the toggle button. The global CSS (rendered by GlobalStyle in ComponentBlack) is added twice and only one is removed when unmounting when in Strict Mode. This is because to Strict Mode “intentionally double-invoking” some lifecycle methods to determine side effects that could be a problem in the upcoming async mode in React. When concurrent mode becomes available and React might call render function multiple times the side effect of setting global styles on render will cause issues like this.
As far as I can tell styled-components
should be React.Strict
compatible and using the createGlobalStyle
util is the recommended way to do global styling with styled-components
, so this seems to be a bug to me.
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 2
- Comments: 15 (4 by maintainers)
Hi, I can see it has been a while but I think I am facing a similar issue with the latest styled-components and latest nextjs with
reactStrictMode: true
defined innext.config.js
Here are the reproducing steps;
Go to latest example provided by nextjs with styled components https://github.com/vercel/next.js/tree/master/examples/with-styled-components
You can install project with the following script
Once porject is created go to top level and add
next.config.js
with the below contentRun development server by
Check
body
styles and styled componentsstyle
tag inhead
. You will see body styles are duplciated.Environment
System: Mac Mini (M1, 2020) OS: macOS BigSur 11.4 CPU: Apple M1
Shell: zsh 5.8 (x86_64-apple-darwin20.0) Binaries: Node: v16.0.0 npm: v7.10.0 npmPackages:
styled-components@5.2.0-test.10
fixes the issue for me, good job. Cheers! 🍻Same here. Ended up moving global styles outside of
React.StrictMode
:instead of
Can y’all try out
styled-components@test
and let me know if it resolves the StrictMode issue?React doesn’t mount the component twice. It renders it twice. Only for the committed render an effect will run (and its cleanup function after that commit is discarded).
Today you can reproduce this realiably if you have a component in a suspense boundary where a sibling suspends i.e. the component renders, the tree suspends, react discards the render and does not commit it: https://codesandbox.io/s/concurrent-mode-suspended-component-commit-lnndy
This can also happen if a low priority render is interrupted by a high priority update but that’s a bit harder to reproduce reliably.
Be careful with actually doing side-effects in that demo and logging them.
react@experimental
in DEV mode will still invoke renders twice but will disable logging for the second invocation. Logging states affected by side-effects is only reasonable in production builds.The issue in #3022 doesn’t just apply to Next.js, it also affects Jest tests and custom SSR solutions.