【问题标题】:How can I extend cases in reducers with Redux ToolKit?如何使用 Redux ToolKit 扩展 reducer 中的案例?
【发布时间】:2022-01-04 18:41:05
【问题描述】:

我正在制作一个插件,其中有一些可以在 reducer 中处理的通用操作。我不确定如何做到这一点,以便有人可以通过相同的操作扩展其他案例。我有一些这样的代码:

export default function createStore() {
  return configureStore({
    preloadedState: initialStoreState,
    reducer: {
      workingStores: workingStoreReducer,
    },
  });
}

reducer 是你所期望的:

export default createReducer(initialWorkingStoreState, (builder) => {
  builder
    // chained for a number of actions rather than just one in reality
    .addCase(anImportedAction, (state, { payload }) => {}); 

基本上有人使用我的插件可能有额外的动作来修改workingStores的状态。

我正在考虑以一种看似复杂的方式解决问题,其中createStore 可以接受回调,然后我的workingStoreReducer 成为getWorkingStoreReducer 的方法,它将接受该回调...

export default function getWorkingStoreReducer(extensions) {
  return createReducer(initialWorkingStoreState, (builder) => {
    exensions(builder); // method would add cases to builder
    builder.addCase(anImportedAction, (state, { payload }) => {}); 

  });
}

这似乎令人费解,所以希望我在文档中遗漏了一个更简单的东西

【问题讨论】:

  • 你能把所有动作都作为命名空间导入吗?
  • @Summer 你能澄清一下吗?
  • 对不起,我的意思是问是否有可能做类似import * as actions from '...'的事情。那么迭代actions 命名空间应该不难。你甚至不需要这个方法。

标签: reactjs redux-toolkit


【解决方案1】:

是否可以提前编写构建器回调?

// Your code
export const createBuilder = (additionalCases = []) => builder => {
    builder.addCase(anImportedAction, (state, { payload }) => {})
        .addCase(anImportedAction, (state, { payload }) => {})

    additionalCases.forEach(([action, reducer]) => builder.addCase(action, reducer)
}

const workingStoreReducer = createReducer(initialWorkingState, createBuilder());

在其他地方,扩展案例并重建减速器

const builderCallback = createBuilder([
  [anExtendedAction, (state, { payload }) => {}],
  [anExtendedAction, (state, { payload }) => {}],
]);
const workingStoreReducer = createReducer(workingState, builderCallback);

// Replace store reducer

【讨论】:

  • 有理由这样做而不是我写的方式吗?我正要以自己的方式作为答案,因为这就是我最终要做的。
【解决方案2】:

我最终使用了我在 OG question 中提出的扩展方法。我找不到明显不同的答案。

我的减速机:

export default function getReducer(extension?: Function) {
  return createReducer<number | null>(null, (builder) => {
    if (typeof extension === 'function') {
      extension(builder);
    }

    builder
      .addCase(eventNewDocAction, (_, { payload }) => {
        const { workingDocumentId } = payload;

        return workingDocumentId;
      })
      .addCase(
        eventCloseDocAction,
        (_, { payload }) => payload.workingDocumentId,
      );
  });
}

我作为extension 传递给上面的方法


export default function (builder) {
  builder.addCase(eventGenericAction, (state, { payload }) => {
    const { documentData, evt } = payload;
    const { workingDocumentId } = documentData;
    const evtName = evt.name as EventType;

    if (activeDocumentEvents.has(evtName)) {
      return workingDocumentId;
    }

    // noop
    return state;
  });
}

然后对于我的reducer 键入configureStore 我有这个:

// extension.workingDocumentId is the above method that adds eventGenericAction
workingDocumentId: getWorkingDocumentIdReducer(
        extensions.workingDocumentId ?? undefined,
      ),

【讨论】:

    猜你喜欢
    • 2020-04-24
    • 2019-03-13
    • 1970-01-01
    • 2020-11-08
    • 1970-01-01
    • 2020-09-13
    • 2021-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多