使用多个中间件时在 redux 存储上正确键入 dispatch

Posted

技术标签:

【中文标题】使用多个中间件时在 redux 存储上正确键入 dispatch【英文标题】:Typing dispatch on a redux store correctly when using multiple middleware 【发布时间】:2021-12-20 17:33:39 【问题描述】:

我正在尝试在使用 thunk 中间件和可选中间件记录器 (redux-logger) 的 redux 存储上配置调度类型。

这可以正确推断商店的 dispatch 上的 thunk 类型...

import  createStore, applyMiddleware  from 'redux';
import thunk,  ThunkMiddleware  from 'redux-thunk';

// ...

const preloadedState = undefined;
export const store = createStore(rootReducer, preloadedState, applyMiddleware(thunk as ThunkMiddleware));

当我扩展中间件以包含条件记录器并将一组中间件传播到 applyMiddleware 时,无法正确推断出商店的 dispatch


import  createStore, applyMiddleware, Middleware  from 'redux';
import thunk,  ThunkMiddleware  from 'redux-thunk';
import  createLogger  from 'redux-logger';

// ...

const middleware: Middleware[] = [thunk as ThunkMiddleware];

if (Settings.environment === 'development') 
  const logger = createLogger( collapsed: (_getState, _action, logEntry) => !logEntry.error );
  middleware.push(logger);


const preloadedState = undefined;
export const store = createStore(rootReducer, preloadedState, applyMiddleware(...middleware));

这让我发疯了,有什么想法在传播中间件数组时如何解决打字问题?

【问题讨论】:

【参考方案1】:

这就是 redux-toolkit 真正派上用场的地方。

他们的docs 提到要这样做

import  configureStore  from '@reduxjs/toolkit'
import  useDispatch  from 'react-redux'
import rootReducer from './rootReducer'

const store = configureStore(
  reducer: rootReducer,
)

export type AppDispatch = typeof store.dispatch
export const useAppDispatch = () => useDispatch<AppDispatch>() // Export a hook that can be reused to resolve types

export default store

【讨论】:

补充:是的,这将考虑到正确键入的中间件。 啊,好吧,我绝对可以看到使用 toolkit 与 thunk 集成的好处,并且默认情况下调度类型正确。除此之外,我可以通过return getDefaultMiddleware().concat(logger)middleware 回调中添加redux-logger,但dispatch 类型仍然被清除。关键是为redux-logger添加类型...yarn add @types/redux-logger【参考方案2】:

您正在执行const middleware: Middleware[] = ...,它显式地消除了存储在数组中的特定类型,并且只保留它们是Middleware,而是执行const middleware = [...] as const 以尽可能多地保留有关内容的信息。 (然后使用类型断言允许在不保留这些类型的情况下修改列表,因为无论如何您都不能依赖)

【讨论】:

啊,有趣,你能扩展一下“然后使用类型断言来允许修改列表而不保留这些类型,因为你无论如何都不能依赖”? 当您执行 as const 时,它会将其标记为只读数组,因此未定义像 push 这样的方法,因此在记录器中覆盖它以获取记录器会给出稍微不正确的类型被添加。更正确的解决方案是使用const middleware: (ThunkMiddleware | LoggerMiddleware)[],这样它就有足够的信息来正确推断调度,并允许您推送记录器,但总的来说这很痛苦。 我发布了答案,然后意识到您为什么要在该列表中开始,并意识到书面答案行不通,所以匆忙修改

以上是关于使用多个中间件时在 redux 存储上正确键入 dispatch的主要内容,如果未能解决你的问题,请参考以下文章

使用 redux 构建 React 应用程序时在哪里存储 WebRTC 流

如何在 Typescript 中使用 redux-thunk 使用 ThunkAction 正确键入 thunk?

如何在 react-redux 中正确键入映射到道具的动作创建者

React Native - Redux:应用程序中相同状态的多个实例

键入时在数字中添加逗号

localstorage 在页面刷新时在 react-redux 应用程序中返回“未定义”