Redux / RTK:为一片创建增强器?

Redux / RTK: create enhancer for one slice?

在我的 Redux / RTK 存储中的一个切片中,要使该切片发挥作用,我需要做的就是使用 createEntityAdapter() and export the setAll CRUD function 创建一个实体适配器。到目前为止,如此简单 - 感谢 RTK :-)

但是,当该切片的数据传入时,我需要“增强”它(或“增强”它,如 Redux docs 所说),即添加从传入数据中派生的更多信息,因为UI(人为的例子)中格式化数据显示的示例。

我为此目的创建了一个增强器,目的是应用程序可以依赖该切片中的数据,一旦它被添加就完成了,即从一开始就包含应用程序组件所需的任何数据。 (这来自以前使用非 UI 组件的不成功方法,该组件后来监听存储更新和增强切片数据 - 这导致更新/计时问题。)

在增强器中,我拦截了感兴趣的操作并在将其添加到商店之前修改了负载(在下面的示例代码中,我只记录了操作,但你明白了......) :

export const mySliceEnhancer = (createStore) => {
  return (rootReducer, preloadedState, enhancers) => {
    const store = createStore(rootReducer, preloadedState, enhancers)

    function newDispatch(action) {
      // intercept only actions related to my slice
      if (action.type === 'mySlice/setAll') {
        console.debug('mySliceEnhancer > newDispatch > action.payload:\n' +
                        JSON.stringify(action.payload, null, 2));
      }

      const result = store.dispatch(action);
      return result;
    }

    return { ...store, dispatch: newDispatch }
  }
}

这有效,但全局应用于整个商店,即 dispatch 被我的自定义版本“覆盖”,以便 any 发送到商店。这让我很担心,因为例如我在 Redux Dev Extension 中丢失了 trace functionality:对于任何 dispatch,我的增强器中的那个都会显示,无论它是否真的改变了什么。

问:有没有办法只将增强器应用于 redux 存储的一个切片?

或者 - 更笼统地问 - 我的方法是个好主意吗?

我认为这是对增强子的用途的误解。

首先,增强器总是包装整个存储对象,并且能够提供自己版本的存储方法,例如 dispatch

其次,“切片缩减器”是一个与商店级代码本身无关的概念。请记住,您实际上只有 一个 reducer - 您传递给 configureStore 的根 reducer。 root reducer 如何选择在内部拆分工作对 store 的其余部分无关紧要——它可能是一个巨大的函数,带有一系列 if 语句,一次处理整个状态树,或使用 combineReducers 按顶级键拆分工作。

第三,如果您正确配置了商店,使用增强器不应消除跟踪功能。根据文档,您可以使用 compose() 组合多个增强器。如果您使用的是 RTK 的 configureStore,您可以传递一个 enhancers 数组,它将负责将它们与 DevTools 增强器正确组合在一起。

最后,由于您真正要做的只是查找特定操作并修改其内容,因此您不需要增强器。一个中间件就可以做到这一点:

const myCustomMiddleware = storeAPI => next => action => {
  if (action.type === 'mySlice/setAll') {
    const state = storeAPI.getState();
    action.payload.someField = state.someValue;
  }

  return next(action);
}

const store = configureStore({
  reducer: rootReducer,
  middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(myCustomMiddleware);
})