You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React定时调用Refresh Token函数时无法读取Context中AuthState的问题

解决Context中令牌在setInterval无法更新的问题

问题原因

setInterval的回调函数会形成闭包,它捕获的是组件首次渲染时的AuthState值。后续Context中的AuthState更新后,回调函数依然引用旧的闭包值,因此无法读取到最新的令牌信息。

解决方案1:用useRef保存最新状态

通过useRef创建引用,配合useEffect监听AuthState变化,实时更新ref的current值,让定时器回调能拿到最新状态:

import { useContext, useRef, useEffect } from 'react';
import { AuthContext } from './你的AuthContext路径';

function YourComponent() {
  const {
    signin,
    state: AuthState,
  } = useContext(AuthContext);
  
  // 保存最新AuthState的引用
  const authStateRef = useRef(AuthState);

  // 监听AuthState变化,同步更新ref
  useEffect(() => {
    authStateRef.current = AuthState;
  }, [AuthState]);

  useEffect(() => {
    const refreshTimer = setInterval(async () => {
      const { token, refreshToken } = authStateRef.current;
      console.log("Running refresh token", token, refreshToken);
      
      // 无令牌时跳过请求
      if (!token || !refreshToken) return;

      try {
        const answer = await ApiRefreshToken(token, refreshToken);
        if (answer.status === 200) {
          signin({
            token: answer.data.token,
            refreshToken: answer.data.refreshToken,
            expires_in: answer.data.expires_in,
          });
        } else {
          setError("刷新令牌失败");
        }
      } catch (err) {
        setError("令牌刷新时网络出错");
      }
    }, 15000);

    // 组件卸载时清除定时器,避免内存泄漏
    return () => clearInterval(refreshTimer);
  }, [signin, setError]);

  // ... 组件其他逻辑
}

解决方案2:随AuthState更新重建定时器

把AuthState加入useEffect的依赖项,每次状态变化时清除旧定时器并创建新的,确保回调捕获最新状态:

import { useContext, useEffect } from 'react';
import { AuthContext } from './你的AuthContext路径';

function YourComponent() {
  const {
    signin,
    state: AuthState,
  } = useContext(AuthContext);

  useEffect(() => {
    const refreshTimer = setInterval(async () => {
      const { token, refreshToken } = AuthState;
      console.log("Running refresh token", token, refreshToken);
      
      if (!token || !refreshToken) return;

      try {
        const answer = await ApiRefreshToken(token, refreshToken);
        if (answer.status === 200) {
          signin({
            token: answer.data.token,
            refreshToken: answer.data.refreshToken,
            expires_in: answer.data.expires_in,
          });
        } else {
          setError("刷新令牌失败");
        }
      } catch (err) {
        setError("令牌刷新时网络出错");
      }
    }, 15000);

    return () => clearInterval(refreshTimer);
  }, [AuthState, signin, setError]);

  // ... 组件其他逻辑
}

额外提示

  • 必须在组件卸载时清除定时器,避免内存泄漏,以上两种方案都通过useEffect的返回函数实现了这一点。
  • 增加令牌存在性检查,避免未登录状态下发起无效请求。
  • 给异步请求添加错误捕获,防止未处理的Promise异常。

内容的提问来源于stack exchange,提问作者Javi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 08:15:45