Home > Software design >  setState in useEffect not working in conjunction with localStorage
setState in useEffect not working in conjunction with localStorage

Time:12-06

This seems unordinary. I'm attempting to simply setState on mount, but it's just going blank on me.

const [info, setState] = useState({
    user_1: '',
    user_2: '',
});

useEffect(() => {

    var personal_1 = window.localStorage.getItem('personal_1');
    var personal_2 = window.localStorage.getItem('personal_2');
    console.log(personal_1);
    if (personal_1 !== null && personal_2 !== null) {
        console.log('Make it easy')
        setState({
            ...info,
            user_1: personal_1,
            user_2: personal_2
        })
    }

}, [])

useEffect(() => {
    console.log('User personal_1 was changed to', info.user_1);
}, [info.user_1])

When I log the effects of this component mounting, it shows

personal_1
Make it easy
User personal_1 was changed to

For some reason instead of setting the state on mount to the value from local storage, it just goes blank. I thought it was probably being set back to being blank from somewhere else in the component, but the info.personal_1 hook only gets called once. Does anyone know why it might potentially be setting the local storage item, but then going blank when the storage item is a normal string?

CodePudding user response:

This is happening because you are not successfully setting the local storage values. Hence, the value of those items will always be blank

You can straight out use the custom React hook (useLocalStorage) I am providing below to get and set items from your localStorage into your web-app

Hook

import { useCallback, useState, useEffect } from "react"

// To use local storage to store, update info
export function useLocalStorage(key, defaultValue) {
  return useStorage(key, defaultValue, window.localStorage)
}

// Common code being used irresp of storage type -> local or session
function useStorage(key, defaultValue, storageObject) {
  
  // Set the "value" (in this hook's state, and return it to the component's state as well) to be the value at passed "key" in storage.
  //  Else, we set it to the defaultValue (which can be a value or a func returning a val)
  const [value, setValue] = useState(() => {
    const jsonValue = storageObject.getItem(key)
    if (jsonValue != null) return JSON.parse(jsonValue)

    if (typeof defaultValue === "function") {
      return defaultValue()
    } else {
      return defaultValue
    }
  })


  // To set a value in the storage using key-val pair
  useEffect(() => {
    if (value === undefined) return storageObject.removeItem(key)
    storageObject.setItem(key, JSON.stringify(value))
  }, [key, value, storageObject])

  // To remove value at given key 
  const remove = useCallback(() => {
    setValue(undefined)
  }, [])

  return [value, setValue, remove]
}

Using the hook in a component :

import { useLocalStorage } from "./useStorage"

export default function StorageComponent() {
  const [age, setAge, removeAge] = useLocalStorage("age", 26)

  return (
    <div>
      <div>
        {age}
      </div>
      <button onClick={() => setAge(40)}>Set Age</button>
      <button onClick={removeAge}>Remove Age</button>
    </div>
  )
}

CodePudding user response:

in second useEffect dependency just add info like this:

useEffect(() => {
    if(info.user_1){
     console.log('User personal_1 was 
      changedto',info.user_1);
   }

 }, [info])
  • Related