ivaylo
ivaylo

Reputation: 841

Using localstorage in useEffect dependency works, but gives warning

I want to use the localStorage getItem in the useEffect dependency. It works, when I set authorization anywhere in my code, it updates the value, but it gives me warning:

useEffect(() => {
    setValue(localStorage.getItem(key))
}, [localStorage.getItem(key)])

The warning:

React Hook useEffect has a complex expression in the dependency array. Extract it to a separate variable so it can be statically checked

What does this mean and how can I extract it. Also I know I can attach listener to localstorage, but can I do it this way?

Upvotes: 1

Views: 11702

Answers (2)

Maxim
Maxim

Reputation: 91

You can use custom hooks for that

const profile = useProfileData();
import { useEffect, useState } from "react";

function getProfileData() {
  return JSON.parse(localStorage.getItem('profile'));
}

export default function useProfileData() {
  const [profile, setProfile] = useState(getProfileData());

  useEffect(() => {
    function handleChangeStorage() {
      setProfile(getProfileData());
    }

    window.addEventListener('storage', handleChangeStorage);
    return () => window.removeEventListener('storage', handleChangeStorage);
  }, []);

  return profile;
}

if you don't get why it's not catched see that question Storage event not firing

in summary it's catching events on different pages

Upvotes: 4

Luke Storry
Luke Storry

Reputation: 6702

localStorage.getItem(key) is a complex expression, useEffect wants a static simple variable or object to compare, it doesn't want to run code inside that array.

I don't know how the rest of your app is set up, but either pass it through as a prop, or just split it out into a variable to pass into the array.


You can alternatively do something like:

window.addEventListener('storage', () => setValue(localStorage.getItem(key)));

Which will fire when storage is changed.

Upvotes: 3

Related Questions