marko2304
marko2304

Reputation: 27

NEXT.JS - LocalStorage reverts value to original instead of saving on refresh

When you first run the component, it should display "1", and on button click, append it by 3, which it does. Value inside localstorage also changes, but when i reload the page, localstorage changes again to 1... what am i missing?

import { useState, useEffect } from 'react'

function Test() {
    
    const [testNum, setTestNum] = useState(1);

    useEffect(() => {
        const data = window.localStorage.getItem("MY_TEST_ITEM");
        setTestNum(JSON.parse(data));
    }, []);

    useEffect(() => {
        window.localStorage.setItem("MY_TEST_ITEM", JSON.stringify(testNum))
    }, [testNum]);

    

  return (
    <div>
        <h1>{testNum}</h1>
        <button onClick={() => { setTestNum(testNum + 3) }}>Add</button>
    </div>
  )
}

export default Test

Upvotes: 1

Views: 1263

Answers (3)

Souhail Benlhachemi
Souhail Benlhachemi

Reputation: 189

Basically you are saying give "testNum" the value 1 on every page refresh, that means your local storage will be always updated to the initial value on the refresh which is 1. So the solution is very obvious, all what you need to do is change the initial state value which should be the localStorage value not the hard coded value. enter image description here

const [loading, setLoading] = useState(true)
const [testNum, setTestNum] = useState(null)
const intialValue = 1

useEffect(() => {
    const localStorageValue = window.localStorage.getItem("YOUR_ITEM_KEY") || intialValue
    setTestNum(Number(localStorageValue))
    setLoading(false)
}, [])

useEffect(() => {
    testNum !== null && window.localStorage.setItem("YOUR_ITEM_KEY", testNum)
}, [testNum])

if(loading) return <div>Loading ...</div>
return(
    <>
        <div>testNum: {testNum}</div>
        <button onClick={e => setTestNum(testNum + 3)}>increment testNum by 3</button>
    </>
)

You can also use the useMemo hook to avoid any unnecessary re-renders

Upvotes: 0

leantrim
leantrim

Reputation: 21

Every time you reload your page your state refreshes.

You have testNum set to 1 so every render it will be set to that.

const [testNum, setTestNum] = useState(1);

Then you have these useEffects running at the same time

    useEffect(() => {
    const data = window.localStorage.getItem("MY_TEST_ITEM");
    setTestNum(JSON.parse(data));
}, []);

  useEffect(() => {
    window.localStorage.setItem("MY_TEST_ITEM", JSON.stringify(testNum))
}, [testNum]);

The second useEffect will render before the first one, thus setting the localStorage to 1.

UseEffect is actually not needed in this case. Try this;

const storageValue = window.localStorage.getItem("MY_TEST_ITEM";
const [testNum, setTestNum] = useState(storageValue ?? 0 );

updateLocalStorageFunc(value){
   setTestNum(value)
   window.localStorage.setItem("MY_TEST_ITEM", JSON.stringify(testNum))
}
    


return (    
<div>
    <h1>{testNum}</h1>
    <button onClick={() => { updateLocalStorageFunc(testNum + 3) }   
</div>)

Upvotes: 1

mohammad mohammadi nodhe
mohammad mohammadi nodhe

Reputation: 2008

try this instead :

const [testNum, setTestNum] = useState(window.localStorage.getItem("MY_TEST_ITEM") === null ? 1 : window.localStorage.getItem("MY_TEST_ITEM"));

Upvotes: 1

Related Questions