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.

[ColorModeProvider] ColorMode and SSR (next.js) not working very well together

See original GitHub issue

Describe the bug When using colorMode with SSR (in this case with next.js) the pages are rendered from the server with light mode. However on the client the pages are rendered with whatever setting is stored on localstorage by use-dark-mode. If the value store is darkMode = true this leads to hydration missmatches. This causes some of the components to be rendered with light mode even if the colorMode is dark.

Check the issue by yourself on https://next-colormode-test.santialbo.now.sh (repo on santialbo/next-colormode-test).

  • Set dark mode on
  • Refresh the page

Expected Behavior I would expect that by default the client renders twice, a first time with light mode so that there are no missmatches and the turns into dark mode.

To Reproduce Check santialbo/next-colormode-test for a minimal reproduction of the issue.

Desktop (please complete the following information): Tried with both Firefox and Chrome.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:41
  • Comments:16 (3 by maintainers)

github_iconTop GitHub Comments

15reactions
jana19-devcommented, Apr 1, 2020

A possible solution I found that does the trick.

Since NextJS’s initial render is server-side, the value read from local storage is always set to ‘light’. We can make use of this by also storing the dark mode preference value in cookies (non-http).

This way, we can grab the initial value from App.getInitialProps and pass it to the ColorModeProvider context when initializing it.

_app.js

import {
  ThemeProvider,
  CSSReset,
  ColorModeProvider
} from '@chakra-ui/core'
import cookies from 'next-cookies'

import theme from '../utils/theme'

const App = ({ Component, pageProps, initialColorMode }) => {
  return (
    <ThemeProvider theme={theme}>
      <ColorModeProvider value={initialColorMode}>
        <CSSReset />
        <Component {...pageProps} />
      </ColorModeProvider>
    </ThemeProvider>
  )
}

App.getInitialProps = async ({ Component, ctx }) => {
  let pageProps = {}
  if (Component.getInitialProps) {
    pageProps = await Component.getInitialProps(ctx)
  }
  const { isDarkMode = 'false' } = cookies(ctx)
  return {
    pageProps,
    initialColorMode: isDarkMode === 'true' ? 'dark' : 'light'
  }
}

export default App

We also have to wrap the toggleColorMode function to set the cookie value on change.

Snippet from my DarkModeToggle button

const DarkModeToggle = ( ) => {
  const { colorMode, toggleColorMode } = useColorMode()

  const handleToggleDarkMode = ( ) => {
    toggleColorMode()
    document.cookie = `isDarkMode=${colorMode === 'light'}`
  }

  ....

And I am not sure if we still need the noflash.js script, but I included it anyway.

// Insert this script in your index.html right after the <body> tag.
// This will help to prevent a flash if dark mode is the default.

(function () {
  // Change these if you use something different in your hook.
  var storageKey = 'darkMode'
  var classNameDark = 'dark-mode'
  var classNameLight = 'light-mode'

  function setClassOnDocumentBody (darkMode) {
    document.body.classList.add(darkMode ? classNameDark : classNameLight)
    document.body.classList.remove(darkMode ? classNameLight : classNameDark)
  }

  // Determine the source of truth from cookie
  const isDarkMode = window.document.cookie.match(/isDarkMode=([^;]*)/)[1] === 'true'
  setClassOnDocumentBody(isDarkMode)
  window.localStorage.setItem(storageKey, JSON.stringify(isDarkMode))
})()
8reactions
franky47commented, Apr 20, 2020

FYI, there has been a very interesting article written by Josh Comeau about solving Dark Mode with SSR, originally aimed at Gatsby, but which raises similar issues as Next.js: https://joshwcomeau.com/gatsby/dark-mode/

Read more comments on GitHub >

github_iconTop Results From Across the Web

Why does chakra-ui colorMode become "dark" when I refresh ...
Colormode switch does work well. But when I refresh the page, it always returns to the darkmode like this video. Video Link. I...
Read more >
Dark-Mode Support with Chakra-UI and Next.js - gsdev
This article is the third article, in a series where we take a look at Building modern web apps with Chakra-UI and Next.js....
Read more >
Advanced Features: Next.js Compiler
Learn about the Next.js Compiler, written in Rust, which transforms and minifies your Next.js application.
Read more >
Color Mode - Chakra UI
Color Mode. Chakra UI comes with built-in support for managing color mode in your apps. By default, most of Chakra's components are dark...
Read more >
Adding dark mode with Next.js, styled-components, and ...
Theme Objects. Knowing whether or not a person wants dark mode is just the first step of the problem. Based on this preference,...
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