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

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,重新解析过期时间并启动定时器。

实现步骤:

  1. 在commonStore中持久化Token到localStorage:
// commonStore.tsx
setToken = (token: string) => {
    localStorage.setItem('token', token);
    // 保留原有逻辑
}
  1. 在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 20:05:30