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

如何在RTK Query的prepareHeaders中访问createApi存储的Token?

在RTK Query的prepareHeaders中获取另一个createApi存储的Token

问题原因

RTK Query的createApi会以你定义的reducerPath作为键,将其状态挂载到Redux Store中。你通过keycloakApi获取的Token存在该API的查询缓存里,而非官方示例中独立的auth切片,所以直接用getState().auth.token自然拿不到。


方法一:直接读取RTK Query的缓存状态

你可以从Store中keycloakApi的查询缓存里提取Token,注意要对应你定义的查询端点名称:

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

const baseQuery = fetchBaseQuery({
  baseUrl: '/your-api-base-url',
  prepareHeaders: (headers, { getState }) => {
    // 获取keycloakApi在Store中的状态
    const keycloakApiState = (getState() as RootState).keycloakApi;
    // 定位到getKeycloakAccessToken查询的缓存数据
    const tokenQuery = keycloakApiState.queries.getKeycloakAccessToken;
    const accessToken = tokenQuery?.data?.access_token;

    if (accessToken) {
      headers.set('authorization', `Bearer ${accessToken}`);
    }
    return headers;
  },
});

注意事项:

  • 只有当getKeycloakAccessToken查询完成且成功时,tokenQuery.data才会存在;如果查询处于pending或failed状态,Token会是undefined。
  • RTK Query的缓存可能会被自动清理(比如缓存过期、调用resetApiState),这种方式依赖缓存的存在性,稳定性不如独立切片。

方法二:将Token存入独立的Redux切片(推荐)

RTK Query的缓存设计用于存储API响应,不适合长期保存认证Token这类全局状态。更可靠的方式是把Token存入专门的auth切片:

1. 创建Auth切片

import { createSlice, PayloadAction } from '@reduxjs/toolkit';

type AuthState = {
  accessToken: string | null;
};

const initialState: AuthState = {
  accessToken: null,
};

const authSlice = createSlice({
  name: 'auth',
  initialState,
  reducers: {
    // 设置Token
    setAccessToken: (state, action: PayloadAction<string>) => {
      state.accessToken = action.payload;
    },
    // 清除Token
    clearAccessToken: (state) => {
      state.accessToken = null;
    },
  },
});

export const { setAccessToken, clearAccessToken } = authSlice.actions;
export default authSlice.reducer;

2. 在keycloakApi中存储Token

通过onQueryStarted钩子,在Token获取成功后将其存入Auth切片:

import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
import { setAccessToken } from './authSlice';

type KeycloakResponse = {
  access_token: string;
};

export const keycloakApi = createApi({
  reducerPath: "keycloakApi",
  baseQuery: fetchBaseQuery({ baseUrl: "/redirect" }),
  tagTypes: [],
  endpoints: (builder) => ({
    getKeycloakAccessToken: builder.query<KeycloakResponse, void>({
      query: () => `/?info=json&access_token_refresh_interval=0`,
      async onQueryStarted(_args, { dispatch, queryFulfilled }) {
        try {
          // 等待查询完成并获取响应数据
          const { data } = await queryFulfilled;
          // 将Token存入Auth切片
          dispatch(setAccessToken(data.access_token));
        } catch (error) {
          console.error('获取Token失败:', error);
        }
      },
    }),
  }),
});

3. 在其他API的prepareHeaders中获取Token

现在就可以像官方示例一样,从Auth切片中读取Token:

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

const baseQuery = fetchBaseQuery({
  baseUrl: '/your-api-base-url',
  prepareHeaders: (headers, { getState }) => {
    const accessToken = (getState() as RootState).auth.accessToken;
    if (accessToken) {
      headers.set('authorization', `Bearer ${accessToken}`);
    }
    return headers;
  },
});

优势:

  • Token存储在独立的全局状态中,不受RTK Query缓存清理的影响。
  • 后续任何需要Token的地方都能统一从Auth切片读取,逻辑更清晰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 17:24:47