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
相关产品推荐
相关产品推荐

