【问题标题】:Wrong state value in event listener handler after setStatesetState 之后事件侦听器处理程序中的状态值错误
【发布时间】:2020-09-10 09:34:48
【问题描述】:

我只是想了解 JavaScript 引擎的这种行为。我有一个事件监听器,它在事件后调用处理程序。在这个处理程序中,我刷新我的令牌并将其放入 redux。在第一次调用时一切正常,但是当处理程序再次调用时,我有令牌刷新错误,因为它发送旧的刷新令牌,与 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}`);
    }
  }
}


【问题讨论】:

    标签: javascript reactjs redux


    【解决方案1】:

    发生这种情况是因为您的处理程序 (handleAppStateChange) 仅在您第一次渲染组件时调用 [onMount (useEffect(() => {...},[]))] 并且它始终使用旧版本的 auth.refresh_token

    为解决此问题,您可以在每次 refresh_token 有新值(getProfileData 之后)时监听 auth.refresh_token 的变化并重新添加您的 EventListener:

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

    您也可以使用React.useCallback 进行记忆回调。 https://reactjs.org/docs/hooks-reference.html#usecallback

    更多信息:Wrong React hooks behaviour with event listener

    【讨论】:

    • 感谢您回答我的问题!我不同意你的观点,我的处理程序不仅在组件挂载时调用,而且在任何AppState(它是 React Native 组件)更改后调用。如果我按照您在此处写的那样做,我的组件将在每次 auth.refresh_token 更改后添加新的侦听器,但我不想要这种行为,所以我在组件挂载上添加了一个侦听器,并且此侦听器 (handleAppStateChange) 的处理程序调用 if需要。我对这个问题想了很多,可能是在令牌刷新后调用处理程序函数时,它看起来在旧范围内并且令牌是旧的。
    • 不,您的 eventListener 注册一次,而不是您的处理函数。因此,您的处理程序具有较旧的值(注册 eventListener 时的状态值)。这是useState()callback 函数的一个非常常见的问题,解决它的最简单方法是我上面提到的listener re-registration
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-16
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    • 1970-01-01
    • 2019-11-07
    相关资源
    最近更新 更多