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

如何在RTK Query的API定义文件中获取Redux-Persist持久化的accessToken

解决方案

1. 让baseQuery动态获取token

RTK Query的fetchBaseQuery支持在请求时动态从store读取状态,无需在API定义阶段就传入固定token。你可以借助baseQuery的第二个参数api,它包含getState方法,能实时获取store中已持久化的accessToken。

示例代码:

import { fetchBaseQuery } from '@reduxjs/toolkit/query/react';

const baseQuery = fetchBaseQuery({
  baseUrl: '/api',
  prepareHeaders: (headers, { getState }) => {
    // 从store中读取最新的持久化token
    const token = getState().auth.accessToken;
    if (token) {
      headers.set('Authorization', `Bearer ${token}`);
    }
    return headers;
  },
});

每次发起API请求时,都会自动从store中取当前有效的token,包括persist完成hydrate后的token。

2. 拦截Hydrate完成前的请求

页面加载时,如果组件在persist完成状态恢复前就发起请求,会因token未就绪导致失败,可通过以下两种方式处理:

方式一:在store中追踪hydrate状态

在自定义slice中添加hydrated状态,监听redux-persist的HYDRATE action:

import { createSlice } from '@reduxjs/toolkit';
import { PURGE, REGISTER, REHYDRATE } from 'redux-persist';

const appSlice = createSlice({
  name: 'app',
  initialState: {
    hydrated: false,
  },
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(REHYDRATE, (state) => {
        state.hydrated = true;
      })
      .addCase(PURGE, (state) => {
        state.hydrated = false;
      })
      .addCase(REGISTER, (state) => {
        state.hydrated = true;
      });
  },
});

export default appSlice.reducer;

然后在组件中,等待hydrated为true后再触发API请求:

import { useSelector } from 'react-redux';
import { useGetDataQuery } from './api';

function MyComponent() {
  const isHydrated = useSelector(state => state.app.hydrated);
  const { data, error, isLoading } = useGetDataQuery(undefined, {
    skip: !isHydrated, // 未完成hydrate时跳过请求
  });

  if (!isHydrated) {
    return <div>加载中...</div>;
  }

  // 渲染业务数据
}

方式二:在baseQuery中等待hydrate完成

封装自定义baseQuery,确保请求发送前store已完成状态恢复:

import { fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import { store } from './store';

const baseQuery = fetchBaseQuery({
  baseUrl: '/api',
  prepareHeaders: (headers, { getState }) => {
    const token = getState().auth.accessToken;
    if (token) {
      headers.set('Authorization', `Bearer ${token}`);
    }
    return headers;
  },
});

const hydratedBaseQuery = async (args, api, extraOptions) => {
  // 轮询等待hydrate完成
  while (!store.getState().app.hydrated) {
    await new Promise(resolve => setTimeout(resolve, 50));
  }
  return baseQuery(args, api, extraOptions);
};

// 定义API时使用封装后的baseQuery
export const api = createApi({
  baseQuery: hydratedBaseQuery,
  endpoints: (builder) => ({
    // 你的API端点定义
  }),
});

3. 确保RTK Query与Redux-Persist兼容

配置store时,将RTK Query的reducer加入persist黑名单(无需持久化API缓存),同时关闭serializableCheck对persist相关action的校验:

import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import { combineReducers, configureStore } from '@reduxjs/toolkit';
import { FLUSH, PAUSE, PERSIST, PURGE, REGISTER, REHYDRATE } from 'redux-persist';
import { api } from './api';
import authReducer from './authSlice';
import appReducer from './appSlice';

const persistConfig = {
  key: 'root',
  storage,
  blacklist: [api.reducerPath], // 不持久化RTK Query缓存
};

const rootReducer = combineReducers({
  [api.reducerPath]: api.reducer,
  auth: authReducer,
  app: appReducer,
});

const persistedReducer = persistReducer(persistConfig, rootReducer);

export const store = configureStore({
  reducer: persistedReducer,
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: {
        ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
      },
    }).concat(api.middleware),
});

export const persistor = persistStore(store);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 15:10:27