如何在 Redux 异步 thunk 中使用 AppDispatch 类型?

Posted

技术标签:

【中文标题】如何在 Redux 异步 thunk 中使用 AppDispatch 类型?【英文标题】:How to use AppDispatch type in in Redux async thunk? 【发布时间】:2021-06-20 08:14:53 【问题描述】:

在我的 Redux 异步 thunk 中,我想使用如下所述推断的 AppDispatch 类型:https://redux.js.org/recipes/usage-with-typescript

我按照这里的说明进行操作:https://redux.js.org/recipes/usage-with-typescript#typing-createasyncthunk

但是当在我的自定义 ThunkApiConfig 类型(以下示例中为MyThunkApiConfig)中使用此 AppDispatch 类型时,将出现循环引用,如下所示:https://codesandbox.io/s/focused-joliot-ho45h?file=/src/usersSlice.ts:

'dispatch' is referenced directly or indirectly in its own type annotation.

这是有道理的,因为调度类型和使用的 thunk 之间存在循环依赖关系。但是如何在异步 thunk 中使用 AppDispatch?

提前感谢您的回答!

【问题讨论】:

这绝对是一个不寻常的设置。使createAsyncSlice 将异步重击作为参数而不是直接使用变量的目标是什么?我可以肯定地找出类型,但我不明白这一点。 类型是dispatchDispatchForMiddlewares<M> & Dispatch<A> 其中M 是中间件,A 是操作类型。我需要查找 thunk 中间件的类型。 【参考方案1】:

MyThunkApiConfig 类型中使用AppDispatch 没有问题。当您这样做 并且 将切片定义为异步操作的函数时,问题就出现了。这会导致切片类型和不应该存在的调度类型之间的紧密耦合。

如果reducer是usersSlice.reducer那么没有问题。此版本使用 updateUser aynsc thunk,而后者又使用类型化调度。但是切片的类型不依赖于调度类型。它只关心状态的类型和它创建的动作(在这种情况下,没有)。

另一方面,您的createAsyncSlice 在其参数类型中使用MyThunkApiConfig。所以这创建了一个循环,其中存储类型取决于切片类型,切片类型取决于存储类型。

通过将updateUser aysnc thunk 传递给函数而不是直接使用它,我基本上无法得到您想要实现的目标。显然,这里的简单解决方案是“不要那样做”。


如果您想直接为AppDispatch 分配类型,您当然可以这样做。不推荐,因为类型比较复杂,依赖很多泛型类型参数。

export type RootState =  users: UsersState 
export type AppDispatch = Dispatch<AnyAction> & ThunkDispatch<RootState, null, AnyAction> 

在您的示例中,您实际上根本不需要MyThunkApiConfig。你可以从updateUser 中删除泛型。它们最终会被推断为&lt;User, void, &gt;,这就足够了。您可以将 slice 参数键入为 asyncThunk: AsyncThunk&lt;User, void, &gt;,这也可以修复循环类型。

【讨论】:

感谢您的回答! - 抱歉,我忘了说明通用 createAsyncSlice 函数的用途。它用于提取存储异步 thunk 状态的通用功能,很像 diode.suzaku.io/advanced/Pot.html。 - 不幸的是,如果我不使用 MyThunkApiConfig 而是使用 asyncThunk: AsyncThunk&lt;User, void, &gt;action.payload 将是 unknown 类型。 - 所以如果我理解正确,你建议在这种情况下手动指定RootStateAppDispatch,对吗?

以上是关于如何在 Redux 异步 thunk 中使用 AppDispatch 类型?的主要内容,如果未能解决你的问题,请参考以下文章

Redux thunk:等待异步函数调度

Redux thunk - 嵌套调度的函数/动作

如何使用 Redux Thunk 链接动态系列的异步操作?

我应该如何将“redux-thunk”用于异步初始状态? (反应/减少)

Redux-thunk 异步调用和状态

使用redux-thunk完成异步connect的第二个参数的对象写法。