Skip to content
Advertisement

How to listen to external variable changes in React

Hope you’re doing well 🙂

I’ve an “auth.js” file, with an aysnc function to get the userId and then store it in session storage. Here it is:

export let userId = sessionStorage.getItem("userId");

const getUserId = async () => {
  if (token) {
    await axios
      .get(`${baseURL}/auth/user`, {
        headers: {
          authorization: token
        }
      })
      .then(function (response) {
        const { data } = response;
        return sessionStorage.setItem("userId", data.userId);
      })
      .catch(function (err) {
        return undefined;
      });
  }
};
getUserId();

Then I access this variable in all components that need it, in order to make other requests. Example in App.js:

useEffect(() => {
    getActiveGames();
    if (token && userId) {
      getCart();
      getWallet();
      getWalletPayments();
    }
  }, []);

The problem is that, in the first render, the userId comes null (obviously) and I’m trying different ways to update or even re-render, in order to get the updated value, but nothing seems to work. I know there’s somehow a basic solution for this, but I just can’t figure it out.

It would be awesome if you could help 🙂

Advertisement

Answer

Option 1 :

If you want to know when userId is filled in sessionStorage:
  1. Add userId in your component state.
  2. Listen for the storage event. See StorageEvent
  3. Add userId as dependency in useEffect.
const getUserId = ()=> sessionStorage.getItem("userId");
const [userId, setUserId] = useState(getUserId());
    
useEffect(() => {
  const storage = (event) => {
    if(event.originalEvent.storageArea===sessionStorage){
       const data = getUserId();
       if(data) setUserId(data);
    } 
  };
  window.addEventListener("storage", storage);
   
  return ()=> window.removeEventListener("storage", storage)
}, []);
    
useEffect(() => {
  getActiveGames();
  if (token && userId) {
     getCart();
     getWallet();
     getWalletPayments();
  }
}, [userId]);

Option 2:

You can manage the userId using Context

  1. In getUserId return data.userId.
const UserContext = React.createContext();

const UserProvider = ({children}) => {
  const [userId, setUserId] = useState(null);

  useEffect(()=> {
    getUserId()
     .then(user => setUserId(user));
  }, []);

  return <UserContext.Provider value={userId}>
          {children}
         </UserContext.Provider>
}

In you App.js

return (<UserProvider>
    ...
</UserProvider)

Using userId from any component in your app:

 const userId = useContext(UserContext);

 useEffect(() => {
    getActiveGames();
    if (token && userId) {
       getCart();
       getWallet();
       getWalletPayments();
    }
 }, [userId]);
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement