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

Time:10-23

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

CodePudding user response:

try this instead :

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

CodePudding user response:

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>)

CodePudding user response:

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

  • Related