Redux-Toolkit RTK-Query测试报错:injectEndpoints读取undefined
解决RTK-Query中
TypeError: Cannot read property 'injectEndpoints' of undefined错误 问题场景
使用Redux-Toolkit的RTK-Query运行测试时,触发TypeError: Cannot read property 'injectEndpoints' of undefined错误。
根因
模块循环导入导致初始化顺序异常:
- api文件中导入了authSlice的
logout动作 - authSlice又导入了通过
api.injectEndpoints创建的authApi,用于编写extraReducers的匹配器
模块加载时api尚未完成初始化,就被authSlice引用,导致调用injectEndpoints时api为undefined。
解决方案
方案1:拆分独立的action文件,切断循环依赖
把auth相关的基础action抽离到独立文件,让api和authSlice都导入这个文件,避免互相引用:
- 创建
authActions.js:
import { createAction } from '@reduxjs/toolkit'; export const logout = createAction('auth/logout'); export const setUser = createAction('auth/setUser');
- 修改authSlice.js:
import { createSlice } from '@reduxjs/toolkit'; import { logout, setUser } from './authActions'; const authSlice = createSlice({ name: 'auth', initialState: { user: null }, extraReducers: (builder) => { builder.addCase(logout, (state) => { state.user = null; }); builder.addCase(setUser, (state, action) => { state.user = action.payload; }); // 用字符串匹配器替代导入authApi,彻底避免循环 builder.addMatcher( (action) => action.type.endsWith('/login/fulfilled'), (state, action) => { state.user = action.payload; } ); } }); export default authSlice.reducer;
- 修改api.js:
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; import { logout } from './authActions'; const baseApi = createApi({ baseQuery: fetchBaseQuery({ baseUrl: '/api' }), endpoints: () => ({}) }); // 注入auth相关端点 export const api = baseApi.injectEndpoints({ endpoints: (builder) => ({ login: builder.query({ query: (credentials) => ({ url: '/login', method: 'POST', body: credentials }), // 如需触发logout,直接使用导入的action onQueryStarted: async (args, { dispatch }) => { // dispatch(logout()); } }) }) }); export const { useLoginQuery } = api;
方案2:将状态更新逻辑移至RTK-Query生命周期
如果不需要在authSlice中监听authApi的端点状态,可以把状态更新逻辑移到RTK-Query的onQueryStarted中,避免authSlice依赖authApi:
// api.js import { setUser } from './authActions'; export const api = baseApi.injectEndpoints({ endpoints: (builder) => ({ login: builder.query({ query: (credentials) => ({ /* ... */ }), onQueryStarted: async (args, { dispatch, queryFulfilled }) => { const { data } = await queryFulfilled; // 直接dispatch更新auth状态的action dispatch(setUser(data.user)); } }) }) });
测试配置注意事项
测试时确保store配置正确,避免重复初始化或循环导入:
// 测试用store配置 import { configureStore } from '@reduxjs/toolkit'; import { api } from './api'; import authReducer from './authSlice'; export const setupTestStore = () => { return configureStore({ reducer: { [api.reducerPath]: api.reducer, auth: authReducer }, middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(api.middleware) }); };
内容的提问来源于stack exchange,提问作者Karine Hiulumian
相关产品推荐
相关产品推荐

