0

Background

I have this React hook and am trying to set the initial state to the value in local storage - if it exists.

function useLocalStorageState(
  key,
  defaultValue = ''
) {
  const [state, setState] = React.useState(() => {
    const valueInLocalStorage = window.localStorage.getItem(key)
    if (valueInLocalStorage) {
      return valueInLocalStorage
    }
    return defaultValue
  })

  React.useEffect(() => {
    window.localStorage.setItem(key, state)
  }, [key, state])

  return [state, setState]
}

This does not work with Next.js because "it executes code first server-side, then client-side. The window object is only present client-side." To solve this, you can use useEffect which Next.js does not process server-side and anything inside it will be processed on the client side and thus have access to the window.

The problem

I could re-write the hook to look like this with useEffect so that has access to the window. However, when the component mounts there is a flash of unstyled content (FOUC) from the defaultValue to the value in localStorage.

function useLocalStorageState(
  key,
  defaultValue = ''
) {
  const [state, setState] = React.useState(defaultValue)

  React.useEffect(() => {
    const valueInLocalStorage = window.localStorage.getItem(key)
    if (valueInLocalStorage) {
      setState(valueInLocalStorage)
    }
  }, [])

  React.useEffect(() => {
    window.localStorage.setItem(key, state)
  }, [key, state])

  return [state, setState]
}

How can I set the state within the hook to be the localStorage value but also avoid this flash of content when the page re-loads to the second state.

It might be worth mentioning I'm using this to store the user's preference on whether or not they're using dark mode.

Hughes
  • 188
  • 2
  • 10
  • 2
    There are really a lot of [tutorials](https://google.com/search?q=dark+mode+nextjs) on this, and [similar](https://stackoverflow.com/search?q=%5Bnext.js%5D+dark+mode) [questions](https://google.com/search?q=dark+mode+nextjs+site%3Astackoverflow.com) here on StackOverflow. Recently one of the users [suggested](https://stackoverflow.com/a/68116169) using [`next-themes`](https://github.com/pacocoursey/next-themes) for doing this with ease. – brc-dd Jun 27 '21 at 19:19

0 Answers0