Redux Toolkit Async Thunk合并代码后出现属性读取与初始化报错问题
问题根因
你遇到的报错是循环依赖导致的模块初始化异常:
- grid slice文件需要导入grid thunk配置
extraReducers - grid thunk文件又需要导入grid slice导出的
gridActions修改加载状态
两个模块互相依赖,加载时其中一个模块还没完成初始化就被另一个引用,就会出现Cannot read properties of undefined类错误。你后续修改为export default test = { ... }的写法进一步触发了新错误:ES模块不支持未声明变量直接赋值导出,test未使用const/let声明,模块加载时还未完成变量初始化就被引用,因此报cannot access test before initialization。
修复方案
方案1(推荐):解除循环依赖,符合Redux Toolkit设计规范
Async Thunk本身会自动触发pending/fulfilled/rejected三个生命周期action,不需要你在thunk内部手动调用slice的action修改加载状态,直接在slice里监听这三个生命周期action即可,从根源上移除thunk对slice的依赖:
第一步:修改thunk代码
import { AsyncThunkAction, createAsyncThunk } from "@reduxjs/toolkit"; import { AnyObject } from "../../models/utils/anyObject"; import { PageOptions } from "../../models/utils/pageOptions"; import { PageResponse } from "../../models/utils/pageResponse"; // 移除对gridActions的导入 interface GridDataProps { thunk: ( arg: PageOptions ) => AsyncThunkAction<PageResponse<AnyObject>, PageOptions, AnyObject>; options?: PageOptions; } // 改为命名导出thunk,不需要包裹在默认导出对象里 export const getData = createAsyncThunk( "grid/data", async (props: GridDataProps, { dispatch }) => { // 移除手动修改carregando的两行代码 const response = await dispatch( props.thunk( props.options || { currentPage: 1, itemsPerPage: 4, } ) ); const result = response.payload as PageResponse<AnyObject>; return result; } );
第二步:修改slice代码
import { createSlice, PayloadAction } from "@reduxjs/toolkit"; import { AnyObject } from "../../models/utils/anyObject"; import { PageResponse } from "../../models/utils/pageResponse"; // 改为导入命名导出的getData thunk import { getData } from "../thunks/grid"; interface GridState { data: PageResponse<AnyObject> | null; carregando: boolean; totalDeItems: number; } const initialState: GridState = { data: null, carregando: false, totalDeItems: 0, }; const gridSlice = createSlice({ name: "grid", initialState, reducers: { // 不需要手动触发的话可以删除setCarregando reducer }, extraReducers: (builder) => { builder // 监听请求开始的pending状态,修改加载状态 .addCase(getData.pending, (state) => { state.carregando = true; }) .addCase(getData.fulfilled, (state, { payload }) => { state.data = payload; state.totalDeItems = payload.totalItems; // 请求成功后关闭加载状态 state.carregando = false; }) // 新增请求失败的rejected状态监听,避免加载状态一直为true .addCase(getData.rejected, (state) => { state.carregando = false; }); }, }); // 不需要的话可以删除gridActions导出 // export const gridActions = gridSlice.actions; export default gridSlice;
方案2(临时修复):调整导出写法
如果不想改动现有逻辑,可以先调整导出格式解决当前报错,但循环依赖问题仍然存在,后续仍可能触发异常:
将thunk的默认导出改为先声明变量再导出:
// 先声明变量再导出 const gridThunks = { getData: createAsyncThunk( // 原有逻辑保持不变 ) } export default gridThunks;
内容的提问来源于stack exchange,提问作者Matheus Foresto Moselli
相关产品推荐
相关产品推荐

