【问题标题】:Actions in multiple slices in Redux toolkitRedux 工具包中多个切片中的操作
【发布时间】:2020-07-30 11:38:09
【问题描述】:

Redux 工具包文档提到在多个 reducer 中使用操作(或者更确切地说是操作类型)

首先,Redux 操作类型并不意味着对单个切片是专有的。从概念上讲,每个 slice reducer “拥有”它自己的 Redux 状态,但它应该能够监听任何动作类型并适当地更新其状态。例如,许多不同的切片可能希望通过清除数据或重置回初始状态值来响应“用户注销”操作。 在设计状态形状和创建切片时请记住这一点。

但是,“记住这一点”,考虑到工具包将切片名称放在每个动作类型的开头,实现这一点的最佳方法是什么?并且您从该切片中导出一个函数并调用该单个函数来调度操作?我错过了什么?这是否必须以某种不使用createSlice 的方式完成?

【问题讨论】:

    标签: redux redux-toolkit


    【解决方案1】:

    看起来这就是extraReducers 的用途:

    Redux 的一个关键概念是每个 slice reducer “拥有”它的 state slice,并且许多 slice reducer 可以独立地响应相同的 action 类型。 extraReducers 允许 createSlice 响应除了它生成的类型之外的其他动作类型。

    action dispatcher 应该知道 action 属于哪个 reducer,这有点奇怪。我不确定拥有reducers extraReducers, 的动机,但您可以使用extraReducers 允许多个切片响应相同的操作。

    【讨论】:

    • RTK 鼓励“按特征”切片。所以通常情况下,大多数动作在它们的核心中都有一个“自然”的特性,而其他减速器只是“顺其自然”。有时,一个动作并没有真正的“主要特征”,在这种情况下,只需使用 createAction 创建它并在多个切片(或普通减速器)中引用它就可以了。
    【解决方案2】:

    我发现在使用createSlice 创建切片时使用extraReducers 功能是最好的方法。

    在我的例子中,我通过为每个相关功能创建一个“SliceFactory”类来实现这一点。我已经使用它来完成示例中的操作,并通过侦听 LOGOUT_USER 操作来重置用户注销时的相关切片。

    参考

    额外的减速器:https://redux-toolkit.js.org/api/createSlice#extrareducer

    我用于工厂的原创文章:https://robkendal.co.uk/blog/2020-01-27-react-redux-components-apis-and-handler-utilities-part-two

    import { createSlice } from '@reduxjs/toolkit';
    import { LOGOUT_USER } from '../redux/actions';
    
    class CrudReducerFactory {
      constructor(slice, state = null, initialState = {}) {
        state = state || slice;
    
        this.initialState = initialState;
    
        const reducerResult = createSlice({
          name: slice,
          initialState: initialState[state],
          reducers: this._generateReducers(),
    
          extraReducers: (builder) => {
            builder.addCase(LOGOUT_USER, (state, action) => {
              return { ...this.initialState };
            });
          },
        });
    
        this.reducer = reducerResult.reducer;
        this.actions = reducerResult.actions;
      }
    
      _generateReducers = () => {
        return {
          // Create One
          requestCreateOne: (state, action) => {
            state.isLoading = true;
          },
          requestCreateOneSuccess: (state, action) => {
            state.isLoading = false;
            state.one = action.payload;
          },
          requestCreateOneError: (state, action) => {
            state.isLoading = false;
          },
          
          // ...snip...
        };
      };
    }
    
    export default CrudReducerFactory;

    这是这样实例化的:

    const factory = new CrudReducerFactory('users', 'users', { foo: 'bah', one: null, isLoading: false } );
    第一个参数是切片的名称,第二个是状态切片,第三个是初始状态。

    然后您可以使用factory.reducerfactory.actions 进行相应的使用。

    【讨论】:

    • 这段代码似乎与这个问题没有任何关系,尤其是像 this._generateReducers 这样的东西不见了,没有解释 stateslice 构造函数参数应该做什么。它并没有真正回答以任何方式提出的任何问题(因为这个问题更像是一个“理解某些东西”的问题)。这只是不完整的代码,没有解释。
    • 为简洁起见,我故意不插入缺少的代码,但考虑到我错误地创建切片的上下文?假设它是不需要的。我试图更全面地解释我的答案,希望对您有所帮助。
    猜你喜欢
    • 2022-12-11
    • 2021-04-03
    • 2021-01-12
    • 2020-10-26
    • 1970-01-01
    • 2020-09-17
    • 2021-08-05
    • 2020-09-02
    • 1970-01-01
    相关资源
    最近更新 更多