Home > Software design >  Local storage is not being updated by useEffect
Local storage is not being updated by useEffect

Time:01-13

I'm trying to persist an array of objects in local storage, but it is not being updated even when the state that holds the array changes.

Everything is working in the UI, even the initial state on local storage is persisted right, and if I log the 'isActive' while I'm clicking on the component that triggers this update it's printing the array whit the modified values as it should, but it seems that the useEffect that has the 'isActive' state on it's dependency array isn't doing its job to provide the actual state for the local storage.

useEffect(() => {
  localStorage.setItem("menuState", JSON.stringify(isActive));
}, [isActive]);
function activate (e) {
  const selected = e.target.id
  setIsActive(
    planets => {
      return planets.map((planet) => {
          if (selected == planet.id && planet.active === true) {
            return planet
          } else if (selected != planet.id && planet.active === true) {
            return {...planet, active: !planet.active}
          } else if (selected != planet.id && planet.active === false) {
            return planet
          } else if (selected == planet.id && planet.active === false) {
            return {...planet, active: !planet.active}
          }
      })      
  }
  )
  setDestinationIndex(selected)
}
const [isActive, setIsActive] = useState(
  () =>
    JSON.parse(localStorage.getItem("menuState")) || [
      { id: 0, active: true },
      { id: 1, active: false },
      { id: 2, active: false },
      { id: 3, active: false },
    ]
);

I realy dont know what to try, because I have the same thing going on other component and works fine, but the difference there is that I'm just persisting a number insted o array of objects, but the code is the same.

I already deleted the key in local storage and ran everything again, but it gets the first state and then doesn't anymore.

local storage screenshot

CodePudding user response:

I think the problem with the array that it hasn't changed across rerenders, probably because you mutate the array directly instead of setting a new array to the isActive variable through setIsActive.

My solution is - try using Kent C. Dodds' useLocalStorageState hook instead, as that hook encapsulates all logic related to setting/getting value to localStorage and you can work with this like with a regular useState hook. I've used it several times and haven't had any problems.

CodePudding user response:

Ok, so as I was replicating the code at the StackBlitz it showed me why it was not working throwing this error:

cannot access 'isActive' before initialization

I should have declared the useEffect after the isActive state like:

const [isActive, setIsActive] = useState(
  () =>
    JSON.parse(localStorage.getItem("menuState")) || [
      { id: 0, active: true },
      { id: 1, active: false },
      { id: 2, active: false },
      { id: 3, active: false },
    ]
);

useEffect(() => {
  localStorage.setItem("menuState", JSON.stringify(isActive));
}, [isActive]);

Thank you guys for the hints!

  • Related