给定一个像这个问题中的用例:
处理依赖于自身状态之外状态的减速器中的动作的最佳实践是什么?上述问题的作者最终只是将整个状态树作为第三个参数传递给每个 reducer。这似乎是严厉和冒险的。Redux FAQ 列出了以下潜在的解决方案:
- 如果 reducer 需要知道来自另一个状态切片的数据,则可能需要重新组织状态树形状,以便单个 reducer 处理更多数据。
- 您可能需要编写一些自定义函数来处理其中一些操作。这可能需要用您自己的顶级 reducer 函数替换 combineReducers。
- 您还可以使用 reduce-reducers 等实用程序来运行 combineReducers 来处理大多数操作,但也可以为跨状态切片的特定操作运行更专业的 reducer。
- 诸如 redux-thunk 之类的异步操作创建者可以通过 getState() 访问整个状态。动作创建者可以从状态中检索额外的数据并将其放入动作中,以便每个减速器都有足够的信息来更新自己的状态切片。
在我的用例中,我有一个“继续”操作,它确定允许用户在多表单/多步骤过程中访问哪个页面,因为这几乎取决于整个应用程序状态,所以我不能在我的任何儿童减速机中处理它。目前,我已将商店拉入动作创建器。我使用商店的当前状态来计算触发到我的“页面”reducer 的操作对象,这会更改活动页面。我可能会在这个动作创建器中安装 redux-thunk 并使用 getState(),但我还没有致力于这种方法。
我想这不是一个太糟糕的解决方案,因为只有一个动作(到目前为止)必须以这种方式处理。我只是想知道是否有更好的解决方案,或者是否有办法重新构建我的状态和减速器以使其更容易,或者我正在做的事情是否符合 Redux 的最佳实践。如果有任何类似的例子,那也会有帮助。
为了提供更多上下文,我的状态树目前如下所示:
{
order: order.result,
items: order.entities.items,
activePage: {
id: 'fulfillment'
// page info
},
pagesById: { // all the possible pages
fulfillment: {
id: 'fulfillment'
// page info
}
}
}
活动页面是用户必须在其中输入数据才能进入下一页的页面/部分)。确定活动页面几乎总是取决于项目状态,有时取决于订单状态。最终结果是一个应用程序,用户连续填写一些表格,一旦表格有效,点击继续。在继续时,应用程序确定所需的下一页并显示它,依此类推。
编辑:我们尝试了结合子减速器实现“全局”减速器的方法。
实现是这样的......
const global = (currentState = initialState, action) => {
switch (action.type) {
default:
return currentState
}
}
const subReducers = combineReducers({
order,
meta
})
export default function (currentState = initialState, action) {
var nextState = global(currentState, action)
return subReducers(nextState, action)
}
全局减速器首先在整个应用程序状态上运行,然后将其结果提供给子减速器。我喜欢这样一个事实,即我不再将一堆逻辑放在动作创建者中,只是为了读取状态的不同部分。
我相信这与 redux 的原则是一致的,因为每个动作仍然会命中每个 reducer,并且调用 reducer 的顺序总是相同的。对这个实现有什么想法吗?
编辑:我们现在使用路由器库来处理页面状态,所以 activePage 和 pagesById 已经消失了。