How to add local storage to persist dark mode theme in Gatsby

Viewed 874

I've tried everything to add local storage to persist theme. Any ideas on how to implement with the existing code? I get a mix of conflicting themes upon first rendering. I tried implementing local storage when setting theme.

const setTheme = type => {
  localStorage.setItem("theme", setState({ ...state, theme: type === "dark" ? theme.light : theme.dark })
}
    
const initState = {
  theme: localStorage.getItem("theme"),
  setTheme: setTheme,
}
    
const [state, setState] = useState(initState)

ThemeProvider.js

    
export const ThemeContext = React.createContext({
      theme: {
      
      },
      setTheme: () => {},
    })
    
export const ThemeContextProvider = props => {
      const theme = {
        light: {
          
        },
        dark: {
         
        },
      }
    
      const setTheme = type => {
        setState({ ...state, theme: type === "dark" ? theme.light : theme.dark })
      }
    
      const initState = {
        theme: theme.light,
        setTheme: setTheme,
      }
    
      const [state, setState] = useState(initState)
    
      return (
        <ThemeContext.Provider value={state}>
          {props.children}
        </ThemeContext.Provider>
      )
    } 
1 Answers

This line does not make sense to me:

const setTheme = type => {
  localStorage.setItem("theme", setState({ ...state, theme: type === "dark" ? theme.light : theme.dark })
}

You want to set an item in localstorage but instead you are setting React state in the setItem function?

Two things to note:

  • do not set the React state inside the localStorage.setItem function
  • you can only save stringified values in localStorage. You cannot save a JavaScript object without turning it into a json string.

This is correct:

const setTheme = type => {
  localStorage.setItem("theme", state.theme }); // only save the theme value "dark" or "light" as a string
}

You need to trigger setting the state according to the values in localStorage or in initialState. Use useffect for this. This answer tells you how.

Related