React+Mobx+Metronic模板中Refresh Token自动触发失败问题
问题分析与解决方案
核心问题1:页面刷新导致定时器丢失
登录成功后你用了window.location.href = '/dashboard',这会触发整页刷新,之前在内存中创建的定时器会被完全清除,自然无法触发。
解决方法:
改用React Router的navigate方法进行单页跳转,避免页面刷新:
// 先在userstore中引入navigate(类组件可通过props或hooks传入,函数式store直接调用) import { useNavigate } from 'react-router-dom'; login = async (creds: UserFormValues) => { try { const user = await agent.Account.login(creds); store.commonStore.setToken(user.token); this.startRefreshTokenTimer(user); runInAction(() => this.user = user); // 替换为单页跳转 this.navigate('/dashboard'); } catch (error) { throw error; } }
核心问题2:定时器的this绑定可能异常
虽然你用箭头函数定义了refreshToken,但setTimeout(this.refreshToken, timeout)中,定时器回调的this可能在执行时丢失绑定(尤其是store实例被重新创建的场景)。
解决方法:
用箭头函数包裹回调,确保this始终指向当前store实例:
private startRefreshTokenTimer(user: User) { const jwtToken = JSON.parse(atob(user.token.split('.')[1])); const expires = new Date(jwtToken.exp * 1000); const timeout = expires.getTime() - Date.now(); // 用箭头函数包裹,锁定this指向 this.refreshTokenTimeout = setTimeout(() => this.refreshToken(), timeout); }
额外保障:页面刷新后重新启动定时器
用户手动刷新页面时,store会重新初始化,定时器也会丢失。需要在App初始化时,从localStorage读取已有的Token,重新解析过期时间并启动定时器。
实现步骤:
- 在
commonStore中持久化Token到localStorage:
// commonStore.tsx setToken = (token: string) => { localStorage.setItem('token', token); // 保留原有逻辑 }
- 在
MasterInit组件中添加初始化逻辑:
// MasterInit.tsx import { useEffect } from 'react'; import { userStore } from '../stores/userstore'; const MasterInit = () => { useEffect(() => { const token = localStorage.getItem('token'); if (token) { const jwtToken = JSON.parse(atob(token.split('.')[1])); const expires = new Date(jwtToken.exp * 1000); const timeout = expires.getTime() - Date.now(); if (timeout > 0) { // 传入包含token的User对象(根据实际类型调整) userStore.startRefreshTokenTimer({ token } as User); } else { // Token已过期,直接触发刷新 userStore.refreshToken(); } } }, []); return null; }
调试建议
- 打开浏览器Console,查看是否有Token解析错误、
this指向错误等报错。 - 在
startRefreshTokenTimer中打印timeout值,确认是正数(负数说明Token已过期,定时器会立即执行)。 - 在
refreshToken方法开头加console.log('触发刷新'),确认是否被调用。
内容的提问来源于stack exchange,提问作者tiakham
相关产品推荐
相关产品推荐

