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
相关产品推荐
相关产品推荐

