Next.js Discord

Discord Forum

Use LocalStorage as a context value hydration error. Next.js 13

Answered
Williamson's Sapsucker posted this in #help-forum
Open in Discord
Williamson's SapsuckerOP
I am trying to use user default settings from localStorage to initialized context provider value or use program default otherwise. thus if no data in localStoriage. I have tried several and it's given me errors

1. I first tried by checking typeof window !== 'undefined' in useEffect and I got hydration error

2. I tried this using custom hooks and it works but server complains localStorage not defined

import { useEffect, useState } from 'react'; export function useLocalStorage(key, initialValue) { const [value, setValue] = useState(() => { const storedValue = localStorage.getItem(key); return storedValue ? JSON.parse(storedValue) : initialValue; }); useEffect(() => { localStorage.setItem(key, JSON.stringify(value)); }, [key, value]); return [value, setValue]; }


Any help ?
Answered by alfon
you can either:
1. declare the setter in useEffect []
2. use dynamic() to skip SSR and load on browser
View full answer

30 Replies

export function useLocalStorage(key, initialValue) {  
  const [value, setValue] = useState(initialValue);

  useEffect(() => {
    const storedValue = localStorage.getItem(key);
    setValue(storedValue ? JSON.parse(storedValue) : initialValue);
  }, [key, initialValue]);

  const setLocalStorageValue = useCallback(v => {
    localStorage.setItem(key, JSON.stringify(v));
    setValue(v);
  }, [key]);

  return [value, setLocalStorageValue];
}
To make this aware of other usages of useLocalStorage with the same key, you should probably use a BroadcastChannel, if necessary.
That's not possible unless your initialValue differs on client/server.
Williamson's SapsuckerOP
I will snap the code here. What it dose is, it first load localStorage data. if it found it it pass to a context for page laod . if not it uses the program default values to laod the page
Williamson's SapsuckerOP
here is the provider it initial data
custom hook
@Williamson's Sapsucker custom hook
As storedValue is const, you will run into an error on line 11 here. Though, since useEffect runs after hydration, you will only have that issue once your hydration error is fixed.
Can you show the consumer of the context? The DesktopNav component that throws the error.
Williamson's SapsuckerOP
ok
@Williamson's Sapsucker here is the provider it initial data
What's the full line 25 here?
Williamson's SapsuckerOP
is a react icon
it use to expand or collpase the nav
No, in the DashboardProvider
Williamson's SapsuckerOP
there is button in the settings that allow user to hide or display nav, so line 25 listen and update the nav component
I have been able to solve the hydration error this simple trick;
you can either:
1. declare the setter in useEffect []
2. use dynamic() to skip SSR and load on browser
Answer
in my case, I fetch the localStorage on click before navigating to another page and add the localstorage value in the Link href
Williamson's SapsuckerOP
const [mount, setMount] = useState(false)

  useEffect(()=>{
   setMount(true)
  })

  if(!mount){
   return <></>
  }
so get the localstorage value before router.push then when you click it, supply the destination link with the localstorage value
that way you don't even need usestate or useEffect at all to load initial selected value
Williamson's SapsuckerOP
Let me try that and update you. thank you
Williamson's SapsuckerOP
dynamic() also works well. Thank you all for your time and effort. I really appreciate that 👍
Checkered Giant
Hi all, I'm using a Next.js app in an app directory and I need a solution for an error that occurs when I initialize easy-peasy. Can someone please provide me with a solution for this issue? https://github.com/dharmveer97/local-storage-easy-peasy
Williamson's SapsuckerOP
what were try to do that brought this error?