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

