如何使用 RootState 修复切片的循环依赖关系?

Rig*_*tti 7 typescript redux redux-toolkit

我最近开始使用redux-toolkit并开始使用createSlice以下他们的文档编写我的减速器。

一个减速器,我们称之为reducerA,导入customAsyncFunction来处理它的回调,这个函数是通过createAsyncThunk它创建的,通过它依次读取RootState调用时thunkApi.getState(),现在的问题RootReducer是导入时,reducerA将被导入生成循环引用。

基本上:RootReducer -> reducerA -> actions -> RootReducer -> ...

下面我尝试简化问题。

// actions.ts file
import { RootState } from "./RootReducer";

export const customAsyncAction = createAsyncAction("myaction", async (_, thunkApi) =>
  const state = thinkApi.getState() as RootState;
  ...
);


// reducerA.ts file
import { customAsyncAction } from "./actions";

const slice = createSlice({
  ...
  extraReducers: {
    [customAsyncAction.fulfilled.toString()]: ... // handles fulfilled action
  }
});

export default slice.reducer;



// RootReducer.ts file
import reducerA from "./reducerA"
import reducerB from "./reducerB"

const reducers = combineReducers({
  reducerA,
  reducerB
});

export type RootState = ReturnType<typeof reducers>; // complains about circular reference
Run Code Online (Sandbox Code Playgroud)

文档的这一部分中,它提到了这种情况发生的可能性,并且有关于将代码拆分为文件的模糊建议。但是,从我的所有尝试中,我似乎无法找到解决此问题的方法。

Хри*_*тов 32

TS认为导入是一个模块,不知道它是一个类型,导入它完全没问题。为了判断它是类型导入,请尝试将其作为类型导入:

import type { RootState } from "./RootReducer";

注意type后面的关键字import。这样 ts/babel/eslint 就知道您导入的是类型,而不是模块,并将其从依赖关系图中排除,从而解决了问题。


mar*_*son 8

仅类型循环引用就可以了。TS 编译器将在编译时解决这些问题。特别是,通常让切片文件导出其减速器,将减速器导入到存储设置中,RootState基于该切片定义类型,然后将类型重新导入RootState回切片文件中。

仅当涉及运行时行为时,循环导入才是一个潜在问题,例如两个切片依赖于彼此的操作。

不幸的是,据我所知,用于捕获循环依赖项的 ESLint 规则无法判断导入的只是一种类型。

  • 这可能不是运行时问题,但它仍然是一个阻碍可维护性的设计问题 (2认同)

Rig*_*tti 4

在阅读了以下有关如何使用TypeScript 的文档部分createAsyncThunk后,我更改了extraReducers使用该builder模式的实现,而不是传递键值对象,并且错误消失了。

// before
const slice = createSlice({
  ...
  extraReducers: {
    [customAsyncAction.fulfilled.toString()]: ... // handles fulfilled action
  }
});

// after
const slice = createSlice({
  ...
  extraReducers: builder => {
    builder.addCase(customAsyncAction.fulfilled, (state, action) => ...)
  }
});
Run Code Online (Sandbox Code Playgroud)

我必须承认我无法确切地指出为什么在第一个条件下它不起作用,而在第二个条件下它却起作用。