ST80
ST80

Reputation: 3903

NextJS localStorage.getItem() method not working on components?

In my nextjs-app I want to use localstorage, to store some values across my application.

so inside the pages-folder I have a [slug].tsx-file where I do this:

export default function Page({ data}) {

   useEffect(() => {
     const page = {
       title: data.page.title,
       subtitle: data.page.subtitle,
       slug: data.page.slug,
     }

     localStorage.setItem("page", JSON.stringify(page))
  })

  return ( ... some html....)
}

this basically stores the title, subtitle and slug for the current route.

Now, inside my components-folder I have a Nav.tsx-file, where I do this:

const Nav= () => {
  const [pageData, setPageData] = useState()

  useEffect(() => {
     const current = JSON.parse(localStoraget.getItem('page'))
     if(current){
        setPageData(current)
     }
  },[])

  return(...some html)

 }

So far, the setItem works and in the application-tab of the google inspector I can see, that the key-values changes, each time a new route/page gets rendered BUT the getItem- always returns the same e.g. the key values do not change at all. What am I doing wrong? Is it maybe because the Nav component only gets rendered once?

Can someone help me out?

Upvotes: 0

Views: 998

Answers (2)

Ilê Caian
Ilê Caian

Reputation: 645

Note: You should avoid using localStorage to share the state over your App. React provides a good way of doing it with ContextAPI or you could use another lib such as Redux/MobX/Recoil.

At the time when the <Nav> component is rendered (and the useEffect runs) the localStorage probably still doesn't have the key-value set.

If you really want to use localStorage (but I suggest not using it), you can create a timeout to execute after some time and will try to get again the value. Something like this could work:

let localStorageTimer = null;

const Nav = () => {
  const [pageData, setPageData] = useState()

  useEffect(() => {
    const getLocalStorageItems = () => {
      const current = JSON.parse(localStorage.getItem('page'))
      if (!current) {
        localStorageTimer = setTimeout(() => getLocalStorageItems, 1000);
      } else {
        clearTimeout(localStorageTimer)
        setPageData(current)
      }
    }

    localStorageTimer = setTimeout(() => getLocalStorageItems, 1000);

    return () => clearTimeout(localStorageTimer)
  }, []);

  return (.. your JSX code)
}

Upvotes: 0

GʀᴜᴍᴘʏCᴀᴛ
GʀᴜᴍᴘʏCᴀᴛ

Reputation: 8918

you have a spelling error from:

localStoraget.getItem('page')

to:

localStorage.getItem('page')

believe your issue also falls under localstorage should be used with async/await so maybe try something like:

const Nav= () => {
  const [pageData, setPageData] = useState()

  useEffect(() => {
    async function settingData() {
      const current = await JSON.parse(localStorage.getItem('page'))
      if(current)setPageData(current)
    }
    settingData()
  },[])

  return(...some html)
}

Upvotes: 1

Related Questions