question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Nextjs with SSR flashes themeless UI

See original GitHub issue

Description

When I have cookieStorageManagerSSR on (and do not have ColorModeScript), the first paint flashes a (mostly) unthemed skeleton.

Link to Reproduction

https://codesandbox.io/s/confident-wing-ztomgs?file=/Chakra.js:378-401

Steps to reproduce

  1. Open Codesandbox link
  2. Notice how ColorModeScript in _document is commented out[1]
  3. Notice how colorModeManager is set in Chakra.js
  4. Open Codesandbox preview to a new window
  5. Refresh the page and notice the first render is jarring. Toggle to dark mode, refresh the page and notice it’s even more jarring. Turn off Javascript (I use Quick Javascript Switcher chrome extension but you can probably do this from the dev tools) and notice how some elements have received the theme like the button text, but most of the page has not. In dark mode this is especially noticeable as you flash from black to white and then the DOM is updated with the CSS classes.

Bonus: 7. Comment back in ColorModeScript. Refresh and notice that it’s so much better! 8. But then toggle the theme and refresh your page. The cookie value was updated but the localStorage was not (confirmed by looking in Application Storage in the devtools). The server now expects one mode and the client expects another which causes a flash (black to white or white to black).

Chakra UI Version

2.2.1

Browser

Chrome 105

Operating System

  • macOS
  • Windows
  • Linux

Additional Information

[1] ColorModeScript in _document is commented out – From the docs: “Also, if you use colorModeManager, you can avoid adding the <ColorModeScript /> to _document.js.” and also in this recent PR https://github.com/chakra-ui/chakra-ui/pull/6035/files#diff-2195e3eb593f2d293a26fbbb447b9efae1bf3b08202902799424c8f62872dff6R11-R12

Overall I would think that the cookie would take precedence over the value in localStorage especially since I’m explicitly passing cookieStorageManagerSSR to the colorModeManager. This can be extra tricky to debug because the localStorage value isn’t cleared out in an obvious way and Chakra still acknowledges it even after ColorModeScript is removed.

There’s really two problems at play here, both relating to Next.js and SSR:

  1. The SSR is lacking. Is it a bug? It’s very unpleasant especially in dark mode. I found this site that’s using Chakra and SSR, but there’s no flashing and when you turn off JS on the frontend, you can see the server responds with a DOM tree populated with classnames, so I think what’s happening now is a bug.
  2. Cookies vs local storage. LocalStorage takes priority and if you’re using both colorModeManager and ColorModeScript you’re going to have a bad time. You’ll have a worse time if you don’t use ColorModeScript at all though.

And a bonus^2! 3. When I manually changed ColorModeScript to dark mode, it never would change for me. I bet it was because light was in my localStorage. So anyone else out there reading this, go to your dev tools > Application > Storage > Local Storage and if you see the key/value there you can right click and delete it 😃

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:7
  • Comments:8 (1 by maintainers)

github_iconTop GitHub Comments

5reactions
VickyKoblinskicommented, Jun 20, 2022

I made substantial progress on this: https://codesandbox.io/s/priceless-night-6f0292?file=/pages/_document.js

__document.tsx

import { ColorMode } from "@chakra-ui/color-mode";
import { ColorModeScript } from "@chakra-ui/react";
import Document, { Html, Head, Main, NextScript, DocumentContext } from "next/document";

import theme from "theme";

type MaybeColorMode = ColorMode | undefined;

function parseCookie(cookie: string, key: string): MaybeColorMode {
  const match = cookie.match(new RegExp(`(^| )${key}=([^;]+)`));
  return match?.[2] as MaybeColorMode;
}

export default class MyDocument extends Document<{ colorMode: string }> {
  static async getInitialProps(ctx: DocumentContext) {
    const initialProps = await Document.getInitialProps(ctx);

    let colorMode: MaybeColorMode = theme.config.initialColorMode;

    if (ctx.req && ctx.req.headers.cookie) {
      colorMode =
        parseCookie(ctx.req.headers.cookie, "chakra-ui-color-mode") || theme.config.initialColorMode;
    }

    return { ...initialProps, colorMode };
  }

  render() {
    const { colorMode } = this.props;

    return (
      <Html data-theme={colorMode} lang="en" style={{ colorScheme: colorMode }}>
        <Head />
        <body className={`chakra-ui-${colorMode}`}>
          {/* <ColorModeScript initialColorMode={theme.config.initialColorMode} type="cookie" /> */}
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

So notably here: I added data-theme and style={{ colorScheme }} to Html and className="chakra-ui-{colorMode}" to body.

This actually works! (I don’t really care about colorMode system so I don’t know if that one works.) This is really fantastic and it actually works great!!

The only todo here would be improving documentation 😃 and exporting parseCookie so it doesn’t need to be copied in here.

0reactions
tombohubcommented, Sep 23, 2022

@jca41

Having the same issue with remix SSR

really? I didn’t notice any issue. See if you notice anything: https://checklist-remix.vercel.app/

Read more comments on GitHub >

github_iconTop Results From Across the Web

Material Ui unstyled asset flashes once every while before ...
Material Ui unstyled asset flashes once every while before rendering with SSR using NextJS · Have you properly set up Material-UI server ...
Read more >
ServerSide Rendering Integration With Flagship [SSR]
This flickering may have an impact on the user experience. In this example, we will show you how to avoid flag value flickering...
Read more >
Fixing the dark mode flash issue on server rendered websites
Bringing a proper solution to dark mode flashing without an ugly hack.
Read more >
How to get a flickerless persistent dark mode in your Next.js ...
Note that this tutorial is made with Material UI, but will work with most other UI libraries ... then you will end up...
Read more >
How to remove dark mode flickering in Next.js + Material UI
Using getInitialProps in _app.js and cookies, it's possible to solve the theme flickering/flashing/fouc problem but it comes with the ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found