使用Redux-Toolkit Query做鉴权时无法存储返回token怎么办?
RTKQ 鉴权token存储与prepareHeaders报错解决方案
1. 解决prepareHeaders "can't read properties of undefined" 报错
该报错通常由两种问题导致:
- prepareHeaders参数顺序错误,未正确解构
getState方法 - auth slice未正确注册到store,导致
getState().auth返回undefined
正确的fetchBaseQuery配置示例
import { fetchBaseQuery, createApi } from '@reduxjs/toolkit/query/react' const baseQuery = fetchBaseQuery({ baseUrl: '你的接口基础地址', // 全局配置credentials,跨域请求自动携带cookie,不需要每个请求单独传 credentials: 'include', prepareHeaders: (headers, { getState }) => { // 必须从第二个参数的对象中解构getState,参数顺序不能调换 const token = getState().auth.token if (token) { headers.set('Authorization', `Bearer ${token}`) } return headers } })
检查store注册配置
确保你的auth slice已经注册到store的reducer中:
import { configureStore } from '@reduxjs/toolkit' import authReducer from './authSlice' import { authApi } from './authApi' export const store = configureStore({ reducer: { // 必须添加auth reducer,否则getState().auth为undefined auth: authReducer, [authApi.reducerPath]: authApi.reducer }, middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(authApi.middleware) })
2. 解决接口返回token无法存储的问题
你需要在登录/注册接口返回token后,主动触发auth slice的更新action,将token存入redux state,需要持久化的话同时写入localStorage。
方案1:组件中调用mutation时存储
import { useLoginMutation } from './authApi' import { setToken } from './authSlice' import { useDispatch } from 'react-redux' function LoginComponent() { const dispatch = useDispatch() const [login] = useLoginMutation() const handleSubmit = async (loginForm) => { try { const res = await login(loginForm).unwrap() // 触发action将token存入redux dispatch(setToken(res.token)) // 登录成功后续逻辑 } catch (err) { // 错误处理 } } }
方案2:RTKQ endpoint中自动存储(无需组件处理)
在authApi的login mutation配置中添加onQueryStarted钩子自动存token:
export const authApi = createApi({ reducerPath: 'authApi', baseQuery, endpoints: (builder) => ({ login: builder.mutation({ query: (credentials) => ({ url: '/login', method: 'POST', body: credentials }), // 请求成功后自动触发token存储 async onQueryStarted(_, { dispatch, queryFulfilled }) { try { const { data } = await queryFulfilled dispatch(setToken(data.token)) } catch {} } }), // 其他接口配置 }) })
持久化token配置(刷新页面不丢失)
修改auth slice的初始化和更新逻辑,自动读写localStorage:
import { createSlice } from '@reduxjs/toolkit' const initialState = { // 初始化时从localStorage读取token token: localStorage.getItem('token') || null, userInfo: null } const authSlice = createSlice({ name: 'auth', initialState, reducers: { setToken: (state, action) => { state.token = action.payload // 更新时写入localStorage localStorage.setItem('token', action.payload) }, logout: (state) => { state.token = null localStorage.removeItem('token') } } }) export const { setToken, logout } = authSlice.actions export default authSlice.reducer
3. credentials参数配置说明
不需要在每个请求提交时传入credentials,全局配置在fetchBaseQuery的参数中即可,可选值:
'include':跨域请求也携带cookie'same-origin':仅同域请求携带cookie'omit':所有请求都不携带cookie
如果单个请求需要覆盖全局配置,可以在对应endpoint的query返回对象中添加credentials字段单独配置。
内容的提问来源于stack exchange,提问作者Valerii Vitenko
相关产品推荐
相关产品推荐

