skip to Main Content

How can I use localstorage value of benchmarkActiveTab in the dependency array? The value is changing in the localstorage but the useEffect isn’t running when the value changes

const [activeTab, setActiveTab] = useState(
  localStorage.getItem("benchmarkActiveTab") || 0
)

useEffect(() => {
  async function getBenchmarkTimes() {
    // this function doesn't run
  }
  getBenchmarkTimes()
}, [activeTab])

I tried to make the useEffect run when the localStorage.getItem('benchmarkActiveTab') changes, but the useEffect doesn’t run.

2

Answers


  1. You need to listen to storage event

    const [activeTab, setActiveTab] = useState(
      localStorage.getItem("benchmarkActiveTab") || 0
    )
    
    useEffect(() => {
      const OnStorageEvent = async () => {
        const value = localStorage.getItem('benchmarkActiveTab') || 0
    
        if (activeTab !== value) {
          // value change
          setActiveTab(value)
    
          // Run getBenchmarkTimes here
          // use value instead of activeTab here because react update after re render
        }
      }
    
      addEventListener("storage", OnStorageEvent)
    
      return () => removeEventListener("storage", OnStorageEvent)
    }, [activeTab])
    
    Login or Signup to reply.
  2. In your code, the state activeTab is only set once during the initial render. It never changes again. So the effect depends on it will never run again either.

    You can use useSyncExternalStore hook. This hook accept two kind of params: subscribe and getSnapshot. Every time subscribe call the callback, React calls getSnapshot and gets a fresh snapshot. If the snapshot changes (when result from Object.is is false), React rerender the component.

    function useLocalStorageValue(key, interval = 100) {
      // run callback intervally
      const subscribe = (callback) => {
        let enabled = true;
        const fn = () =>
          setTimeout(() => {
            callback();
            if (enabled) fn();
          }, interval);
        fn();
        return () => {
          enabled = false;
        };
      };
    
      // get value from localstorage
      const getSnapShot = () => {
        return localStorage.getItem(key);
      };
    
      return useSyncExternalStore(subscribe, getSnapShot, getSnapShot);
    }
    

    See full example here.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search