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

Redux createApi页面刷新Token为空致API请求失败求助

问题分析与解决方案

问题根源

页面刷新后Redux的auth状态会被重置为初始值,此时useGetProfileQuery会立即发起请求,但token还未从本地存储恢复,导致请求头无有效token,接口返回错误;而切换路由再返回时,auth状态已完成初始化,token存在,所以接口请求正常。

解决步骤

1. 持久化用户登录状态

登录成功后将用户信息(含token)存入本地存储,同时在auth切片初始化时从本地读取状态:

// authSlice.js
import { createSlice } from '@reduxjs/toolkit';

// 初始化时优先从localStorage读取用户信息,无数据则设默认值
const initialState = {
  userInformation: JSON.parse(localStorage.getItem('userAuth')) || { token: null }
};

const authSlice = createSlice({
  name: 'auth',
  initialState,
  reducers: {
    setUserAuth: (state, action) => {
      state.userInformation = action.payload;
      localStorage.setItem('userAuth', JSON.stringify(action.payload));
    },
    clearUserAuth: (state) => {
      state.userInformation = { token: null };
      localStorage.removeItem('userAuth');
    }
  }
});

export const { setUserAuth, clearUserAuth } = authSlice.actions;
export default authSlice.reducer;

2. 控制API请求时机

修改Profile组件,仅当token存在时发起请求,或在token加载完成后重新触发请求:

import { useSelector, useEffect } from 'react-redux';
import { useGetProfileQuery } from './profileApi';

const Profile = () => {
  const token = useSelector(state => state.auth.userInformation.token);
  // token不存在时跳过请求
  const { data, error, isLoading, refetch } = useGetProfileQuery(undefined, {
    skip: !token
  });

  // 监听token变化,token出现时重新发起请求
  useEffect(() => {
    if (token) {
      refetch();
    }
  }, [token, refetch]);

  return (
    <div>
      {error && <p>请求出错</p>}
      {isLoading && <p>加载中...</p>}
      {data?.profiles?.[0]?.firstName && <p>{data.profiles[0].firstName}</p>}
      {!token && <p>请先登录</p>}
    </div>
  );
};

export default Profile;

3. 优化API请求头处理(可选)

在prepareHeaders中补充空token的逻辑,同时可配置缓存重试:

export const profileApi = createApi({
  reducerPath: 'profileApi',
  baseQuery: fetchBaseQuery({
    baseUrl: '(MY-API URL)/api/v1/',
    prepareHeaders: (headers, { getState }) => {
      const token = getState().auth.userInformation.token;
      if (token) {
        headers.set('authorization', `Bearer ${token}`);
        headers.set('Accept', 'application/json');
      }
      return headers;
    },
    // 可选:状态更新时自动重试请求
    refetchOnMountOrArgChange: true
  }),
  endpoints: (builder) => ({
    getProfile: builder.query({
      query: () => 'profile/all',
    }),
  }),
});

补充说明

  • 需保证auth切片的初始化逻辑优先于API请求执行,确保store启动时就加载本地存储的用户状态
  • 使用skip参数可避免无token时发起无效请求,减少错误日志
  • RTK Query自带缓存机制,切换路由时会读取缓存并验证有效性,此时token已存在,因此请求正常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 21:22:48