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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 07:45:00