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

React组件挂载时API请求报403错误,刷新页面后恢复正常

React组件首次加载API请求403,刷新后正常的解决方案

问题原因

核心问题是请求实例创建时机与Redux Persist状态恢复不同步:

  • 封装userRequest时,TOKEN是在模块导入阶段直接从localStorage读取的,但此时Redux Persist可能还没完成从本地存储恢复用户状态的操作,导致TOKEN为空,请求头缺少有效认证信息,触发403错误。
  • 刷新页面时,localStorage里的用户状态已经存在,模块重新导入时能读取到有效的TOKEN,所以请求正常通过。

解决方案

方案1:用Axios拦截器动态设置请求头

修改请求封装代码,每次发起请求前实时从localStorage获取最新的TOKEN,避免模块初始化时的状态滞后问题:

import axios from "axios";

const BASE_URL = "http://localhost:5000/api/";

export const publicRequest = axios.create({
  baseURL: BASE_URL,
});

export const userRequest = axios.create({
  baseURL: BASE_URL,
});

// 添加请求拦截器,每次请求前动态注入TOKEN
userRequest.interceptors.request.use((config) => {
  const user = JSON.parse(localStorage.getItem("persist:root"))?.user;
  const currentUser = user && JSON.parse(user).currentUser;
  const TOKEN = currentUser?.accessToken;

  if (TOKEN) {
    config.headers.token = `Bearer ${TOKEN}`;
  }
  return config;
});

方案2:监听用户状态变化再发起请求

如果项目用了Redux,通过useSelector获取用户状态,将其作为useEffect的依赖项,确保只有当用户状态加载完成后才发起API请求:

import { useSelector } from 'react-redux';

const [orders, setOrders] = useState([]);
// 从Redux store获取当前用户
const currentUser = useSelector(state => state.user.currentUser);

useEffect(() => {
  const getOrders = async () => {
    // 无有效TOKEN时直接返回,避免无效请求
    if (!currentUser?.accessToken) return;
    
    try {
      const res = await userRequest.get(
        "orders/find/63c18620cf0c78c4a0cf7ff9"
      );
      setOrders(res.data);
    } catch (error) {
      console.error(error);
    }
  };

  getOrders();
}, [currentUser]); // 依赖用户状态,状态更新时自动重新请求

方案3:确保Redux Persist状态恢复完成后再渲染组件

使用redux-persist的PersistGate组件,包裹你的根组件,确保只有当状态从本地存储恢复完成后,才渲染页面内容:

import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import { persistStore } from 'redux-persist';
import store from './store';
import App from './App';

const persistor = persistStore(store);

ReactDOM.render(
  <Provider store={store}>
    {/* loading可以设置为自定义加载组件 */}
    <PersistGate loading={null} persistor={persistor}>
      <App />
    </PersistGate>
  </Provider>,
  document.getElementById('root')
);

这种方式下,组件渲染时Redux状态已经完全恢复,模块导入时能读取到有效的TOKEN,首次加载的API请求就能正常携带认证信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 06:20:06