在Next.js中用Redux Toolkit集成Mutex时出现getState未定义错误
解决Next.js + Redux Toolkit Query + async-mutex 中的 getState 未定义错误
问题原因
该错误的核心是循环依赖或baseQuery包装函数参数传递错误:
- 若store与api存在循环导入,会导致api初始化时store上下文未就绪;
- 若重鉴权的baseQuery包装函数未正确接收
api参数,调用api.getState()时就会出现undefined。
解决方案
1. 正确实现带重鉴权的baseQuery并使用mutex
重构api文件,确保mutex实例化、baseQuery包装逻辑正确,且不直接导入store:
import { Mutex } from 'async-mutex'; import { fetchBaseQuery, createApi } from '@reduxjs/toolkit/query/react'; import { BASE_API_V1 } from './constants'; // 实例化mutex,确保作用域在api创建之前 const mutex = new Mutex(); // 基础fetch查询配置 const baseQuery = fetchBaseQuery({ baseUrl: BASE_API_V1 }); // 带自动重鉴权的baseQuery包装函数 const baseQueryWithReauth = async (args, api, extraOptions) => { // 先执行正常请求 let result = await baseQuery(args, api, extraOptions); // 捕获401过期错误,触发重鉴权逻辑 if (result.error && result.error.status === 401) { // 确保同一时间只有一个刷新请求执行 if (!mutex.isLocked()) { const releaseLock = await mutex.acquire(); try { // 通过api参数获取当前state,避免直接导入store const { auth } = api.getState(); // 调用刷新token的接口(需提前在endpoints中定义refreshToken) const refreshResponse = await api.dispatch( api.endpoints.refreshToken.initiate({ refreshToken: auth.refreshToken }) ); if (refreshResponse.data) { // 刷新成功后重新执行原请求 result = await baseQuery(args, api, extraOptions); } else { // 刷新失败,执行登出/跳转登录页逻辑 // window.location.href = '/login'; } } finally { // 释放mutex锁 releaseLock(); } } else { // 已有刷新请求在执行,等待锁释放后重试 await mutex.waitForUnlock(); result = await baseQuery(args, api, extraOptions); } } return result; }; // 创建RTK Query API实例 export const api = createApi({ reducerPath: 'api', baseQuery: baseQueryWithReauth, endpoints: (builder) => ({ // 在这里定义你的接口endpoint // 示例:getUser: builder.query({ query: (id) => `/users/${id}` }) }) });
2. 确保store初始化顺序,避免循环依赖
在store文件中,确保先导入完全定义好的api,再创建store:
import { configureStore } from '@reduxjs/toolkit'; import { api } from './api'; // 确保api已完成定义 export const store = configureStore({ reducer: { [api.reducerPath]: api.reducer, }, middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(api.middleware), });
3. 检查Next.js SSR上下文(若使用)
如果项目使用SSR(如getServerSideProps),需确保每个请求的store实例独立,但mutex可保持全局单例(仅用于客户端请求锁)。若服务器端也需要重鉴权,建议将mutex的实例化放在客户端专属代码中,避免SSR时的上下文冲突。
关键注意事项
- 绝对不要直接在api文件中导入store,所有状态获取必须通过
baseQuery的api.getState()方法; - 确保baseQuery包装函数严格接收
args, api, extraOptions三个参数,缺一不可; - mutex的锁必须在
finally块中释放,避免死锁。
内容的提问来源于stack exchange,提问作者Garalax
相关产品推荐
相关产品推荐

