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

React登录跳转Dashboard后需手动刷新才可加载数据问题咨询

问题根因

首次登录跳转Dashboard不触发接口请求、手动刷新后才正常加载的核心原因是Axios实例请求头初始化时机错误,同时存在一处useEffect使用隐患:

  1. 查看axios.js代码可知,你在调用axios.create()创建实例时,直接同步执行getHeader()生成请求头,该逻辑仅会在Axios模块第一次被应用导入时执行一次:
    • 未登录状态下应用启动,模块初始化时localStorage内无token,生成的请求头不携带Authorization鉴权字段
    • 登录成功后token被存入localStorage,但已经创建完成的Axios实例不会重新执行getHeader()更新请求头,此时发起Dashboard数据请求时用的还是旧的无鉴权头配置,大概率会被前端路由鉴权或后端接口拦截,根本走不到请求成功的逻辑
    • 手动刷新页面时整个应用重新加载,Axios模块重新初始化,此时localStorage内已经存在有效token,生成的请求头携带正确鉴权信息,请求可以正常发送
  2. 额外隐患:Dashboard页面的两个useEffect依赖数组为空,后续修改筛选条件时不会自动触发新的数据请求,且现有请求逻辑没有错误捕获,请求失败时无任何提示,会提升排查难度。
修复方案

1. 修复Axios动态请求头逻辑

不要在创建实例时写死headers配置,改用Axios请求拦截器,每次发送请求前实时从localStorage读取最新token生成请求头,修改后的axios.js代码如下:

import axios from 'axios';
import history from "../history";
const apiUrl = `https://test.mydomain.it/api/auth/`;

const api = axios.create({
    baseURL: apiUrl,
})

// 请求拦截器:每次发请求前动态注入最新鉴权头
api.interceptors.request.use((config) => {
    const token = localStorage.getItem("token");
    const expiration = localStorage.getItem("token_exp");
    // token过期直接清理状态跳登录页
    if (expiration * 1000 < Date.now()) {
        localStorage.removeItem("token");
        localStorage.removeItem("token_exp");
        history.push("/");
        return Promise.reject("登录已过期");
    }
    // 动态拼接请求头
    config.headers = {
        "Content-Type": "application/json; charset=UTF-8",
        "Accept": 'application/json; charset=UTF-8',
        ...(token ? { Authorization: `Bearer ${token}`, useCredentials: true } : {})
    }
    return config;
}, (error) => {
    return Promise.reject(error);
})

// 可选:添加响应拦截器统一处理未授权错误
api.interceptors.response.use((res) => res, (error) => {
    if (error.response?.status === 401) {
        localStorage.removeItem("token");
        localStorage.removeItem("token_exp");
        history.push("/");
    }
    return Promise.reject(error);
})

export default api;

2. 优化Dashboard页面数据请求逻辑

合并重复请求逻辑、补全依赖、添加错误捕获,支持筛选条件变化自动拉取新数据,修改后的请求相关代码如下:

const fetchDashboardData = async () => {
    try {
        if(dashboardfilter.year === "" && dashboardfilter.tributo === "" ){
            const res = await getDashboard_Data();
            setChart(res.data.data);
        }else{
            // 此处补全带筛选参数的请求逻辑
        }
        const res1 = await getDashboard_Data_byYear(dashboardfilter.year);
        setBarChart(res1.data.data);
    } catch (err) {
        console.error("加载仪表盘数据失败:", err);
        // 可在此处添加页面错误提示
    }
}

useEffect(() => {
    fetchDashboardData();
// 依赖数组添加dashboardfilter,筛选条件变化时自动重新请求
}, [dashboardfilter]);

3. 校验登录跳转逻辑

确认getToken方法是在token成功写入localStorage之后才返回resolve,你现有登录代码中await getToken()执行完成后再判断token、执行跳转的逻辑没有问题,只要保证token写入操作是同步或被await等待即可。

验证排查步骤

修改完成后打开浏览器开发者工具的Network面板,登录跳转Dashboard时观察请求状态:

  • 如果能看到接口请求,检查请求头是否携带Authorization字段,未携带则重新检查拦截器逻辑
  • 如果请求正常发送但返回401状态码,检查localStorage内存储的token值是否正确、是否在有效期内
  • 如果完全没有发出接口请求,检查路由鉴权逻辑是否在页面加载前就触发了重定向,同时查看Console面板是否有JavaScript报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 19:09:21