React+ReduxToolkit使用Async Thunks测试时报pending属性未定义错误
问题根源
你遇到的报错是循环导入导致的:异步thunk拆分到独立文件后,thunk文件与slice文件、全局store导出链路之间形成了循环依赖,模块初始化时slice文件执行到extraReducers的对象字面量计算逻辑时,导入的thunk还未完成初始化,值为undefined,因此读取pending属性抛出错误。生产运行时没有触发是因为运行时模块加载顺序刚好避开了循环依赖的影响,测试环境的导入链路不同才暴露了问题。
解决方案
方案1:改用builder回调形式定义extraReducers(最快捷,无需调整现有文件结构)
createSlice的extraReducers支持两种写法,你当前用的对象字面量写法会在模块初始化阶段就计算所有key值,而builder回调形式会被RTK延迟到所有模块初始化完成后再执行,完美规避循环导入导致的thunk未初始化问题。
将你的slice代码修改为如下写法即可:
import { myAsyncThunk } from './some-thunks.file.ts'; const mySlice = createSlice({ // 其他配置不变 extraReducers: builder => { builder .addCase(myAsyncThunk.pending, state => { // pending逻辑 }) .addCase(myAsyncThunk.fulfilled, (state, action) => { // 成功逻辑 }) .addCase(myAsyncThunk.rejected, state => { // 失败逻辑 }) } })
方案2:梳理导入链路消除循环依赖
如果要从根源解决问题,可以排查你的导入链:
- 检查拆分出的thunk文件是否导入了对应slice文件中的内容(比如状态类型、其他同步action)
- 将公共的类型、常量抽取到独立的第三方文件,避免slice和thunk之间的互相导入
方案3:测试时按需注入reducer
你当前封装的render方法默认加载了全局完整reducer,才会触发与当前测试组件无关的orders模块的导入逻辑。可以调整封装的render方法,支持传入自定义reducer,测试时仅注入当前组件依赖的reducer即可:
// 调整自定义render方法的参数 function render(ui, { preloadedState, reducer = rootReducer, store = configureStore({ reducer, preloadedState }), ...renderOptions } = {}) { // 原有包装逻辑不变 }
测试登录组件时仅传入auth相关reducer,不会加载无关的orders模块,自然不会触发对应报错:
import { authReducer } from 'path-to-auth-slice'; const { baseElement } = render(<SigninComponent />, { reducer: { auth: authReducer } })
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

