我有一个 reducer 树,看起来像这样:

module.exports = combineReducers({
    routing: routeReducer,
    app: combineReducers({
        setup: combineReducers({
            sets,
            boosters
        }),
        servers: combineReducers({
            servers
        })
    })
});

现在,setup key 包含一个表单,一旦我们提交了该表单,就需要将其重置。但是,我无法访问整个setup树,因为使用CombineReducers意味着reducer仅在树的叶子节点(在这种情况下为setsboosters)上操纵数据。

我的第一个冲动是制作一个减少整个安装树的函数,如下所示:
function setup(state, action){
    //If there's an action that affects this whole tree, handle it
    switch(action.type){
        case "FORM_SUBMIT": //DO STUFF
        break;
    }

    //Otherwise just let the reducers care about their own data
    return combineReducers({
                sets,
                boosters
    })(state);
}

但这是行不通的,而且还会弄乱我的第一个代码示例的漂亮树结构。

使用redux是否有更好的解决方案?

最佳答案

combineReducers是一个很好的模式,因为它倾向于强制执行这样的想法,即reducer的作用域应该是商店的非重叠子集,并且应与商店本身的结构脱钩。它认为您应该减少叶子而不是分支,并且可以减少分支。

也就是说,使用替代模式可能有充分的理由。正如我在related question中提到的那样,您可以选择完全不使用combineReducers并根据需要分解分解器。

在您的情况下,您可以装饰内部combineReducers:

module.exports = combineReducers({
    routing: routeReducer,
    app: combineReducers({
        setup: setupReducer(
            combineReducers({
                sets,
                boosters
            })
        ),
        servers: combineReducers({
            servers
        })
    })
});

在这里,setupReducerhigher-order function。这可能很难理解,但是这是我的处理方法:
  • 我们知道setupReducer将reducer作为参数,因为我们正在将combineReducers的结果传递给它。
  • 我们知道combineReducers返回的reducer的签名是(state, action) => state
  • 我们也知道setupReducer必须返回一个reducer,它也是签名(state, action) => state的函数。

  • 换句话说,它需要一个缩减器,并返回一个缩减器:((state, action) => state) => ((state, action) => state)。所以它可能看起来像:
    function setupReducer(subReducer) {
        return (state, action) => {
            //If there's an action that affects this whole tree, handle it
            switch(action.type){
                case "FORM_SUBMIT":
                    // ... create newState
                    return newState;
                default:
                    return subReducer(state, action);
            }
        }
    }
    

    我已将您的逻辑流程放在上面,但为慎重起见,您可能希望无条件调用subReducer,然后修改其输出。否则,必须确保未调用分支的对象始终产生相同形状的对象,这似乎是耦合的潜在粘性点。

    关于reactjs - 使用Redux CombineReducers减少整个子树,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34427851/

    10-11 19:35