Vladyslav Stepaniuk
Vladyslav Stepaniuk

Reputation: 13

Wrong state value in event listener handler after setState

I just want to understand this behavior of the JavaScript engine. I have an event listener, which calls handler after event. In this handler I refresh my token and put it in the redux. On the first call all is OK, but when handler calls again, I have token refreshing error, because it sends old refresh token, not the same as in redux.

import React, {useEffect, useState} from 'react';
import {useSelector, useDispatch} from 'react-redux';
import {setAuthData} from '../redux/actions/actions';



const Distributor = props => {
  const dispatch = useDispatch();
  const auth = useSelector(store => store.Auth); // auth from redux


  useEffect(() => {                              // setting my event listener
    AppState.addEventListener('change', handleAppStateChange);
    return () => {
      console.log('distributor unmount');
      AppState.removeEventListener('change', handleAppStateChange);
    };
  }, []);

  const handleAppStateChange = nextAppState => {   // my handler
    if (nextAppState === 'active') {
      getProfileData()
    }
  };

async function getProfileData() {                 // function that processes refreshing token
    try {
      const responseFromAuth = await refreshToAccessToken(
        auth.refresh_token,
      ).then(res => res.json());
      if (responseFromAuth.access_token) {
        dispatch(setAuthData(responseFromAuth));
      } else {
        console.log(
          `Error getting access token from refresh in distributor: ${
            responseFromAuth.error_description
          }`,
        );
      }
    } catch (e) {
      console.log(`Error getting profile data: ${e}`);
    }
  }
}


Upvotes: 1

Views: 1077

Answers (1)

Alireza Esfahani
Alireza Esfahani

Reputation: 741

It happened because your handler (handleAppStateChange) calls only in the first time you render the component [onMount (useEffect(() => {...},[]))] and it always has the older version of your auth.refresh_token

for solving this issue, you can listen to auth.refresh_token changes and re-add your EventListener every time refresh_token has a new value (after getProfileData):

 useEffect(() => {                              // setting my event listener
    AppState.addEventListener('change', handleAppStateChange);
    return () => {
      AppState.removeEventListener('change', handleAppStateChange);
    };
  }, [auth.refresh_token]);

also you can use React.useCallback for a memoized callback. https://reactjs.org/docs/hooks-reference.html#usecallback

for more information: Wrong React hooks behaviour with event listener

Upvotes: 1

Related Questions