SSR broken with dynamic, cookie-based theme (dark mode doesn't work)
See original GitHub issueHello!
I discovered an issue in my app (Next JS with Material UI v5 and “next-dark-mode”), and hoped you might be able to help 😃
TLDR:
Determining the theme based on a cookie seems to generate two sets of stylesheets on the server. This breaks the theming on the client.
Code sandbox:
https://codesandbox.io/s/vigorous-noether-5xxr6
GIF:
Steps to reproduce:
- Open up the project from the CodeSandbox linked above and let the homepage load.
- Refresh the page. You should see nothing out of the ordinary (I assume because there’s no theme cookie yet).
- Now click the “switch theme” button in the middle. The theme should switch correctly to light / dark.
- Now refresh the page —> ??? The background should be the wrong color!
- Click the button to switch themes and you should see that the “new theme” is correct, and looks a lot like the old broken theme.
- Refresh the page again, and you should see the same bug with the opposite color as well — parts of the page are using the correct colors, while other parts are not.
Switching themes twice “fixes” the theme to have the right colors, but only until the next page visit / next refresh.
It looks like the cookie seems to work incorrectly when theme styles are generated on the server side.
Details:
After upgrading to MUI 5 last weekend, I noticed that the footer of my app always had the links in the wrong color for some reason. So I tried to investigate.
I saw that I seemed to be getting two sets of styles on the client, as can be seen in the screenshot below:
These conflicted with each other in somewhat unpredictable ways. In my case the result was that 99% of the app seemed to look fine, except for the footer. In the CodeSandbox above, it seemed to affect the body background color as well.
I’m using the “next-dark-mode” library, which uses a cookie to store the user’s dark mode preference. This cookie is supposed to let my Theme
component determine the right theme during server-side rendering. In my app all pages are currently server-side rendered (i.e. no static pages), but the theming bug is still present.
In the gif above you can see that the theme seems to be generated correctly when the user clicks a button to switch modes, but breaks when the user comes back to the page (e.g. after refreshing).
If I remove getInitialProps
from my _document.tsx
file, then this bug does not occur.
.
I’m hoping that this is just a user-error on my part. However, I didn’t have this issue in MUI 4 (back then I used ServerStyleSheets
from MUI styles and merged them in getInitialProps
in _document.tsx
in much the same way as now.)
To be honest I have no idea what’s really happening under the hood here. I’m a bit new to Next JS and certainly very new to emotion (e.g. I have no idea whatsoever how it’s caching works). But before I spend many hours debugging and diving down the info rabbit hole of how server-side rendered styles work, I thought I’d try my luck asking for help here first 😄
While I’m here, allow me to say that I really love this library. It made my MUI 5 migration very smooth and easy, I have no idea how many hours it would’ve taken if I had to refactor everything to styled components.
Also, I really love how the results of functions return objects. It makes it so easy to just autocomplete the results of everything, so I never make typos and I never have to worry about naming things. And of course being a big TS fan I love that everything could be kept type-safe 😄 So yeah, even if I need to take this issue to another library, just wanted to say thanks a lot for your hard work! 😄
Issue Analytics
- State:
- Created 2 years ago
- Reactions:2
- Comments:5 (3 by maintainers)
Top GitHub Comments
@Deckstar It’s fixed in v2.
Updated sandbox
Thank you for reporting, it was a big issue that needed to be addressed.
Best
Found the bug. I am to blame. Fixing.