我会在 Dan Abramov 发现这个帖子并写下另一个惊人的答案之前尝试解释 :-)
缺点:
reducer A 的函数可能需要有关 reducer B 信息的信息,但因此无法访问。
这个问题并没有真正发生,因为这完全取决于你应该如何组合减速器。如果reducer 只对状态树的一部分感兴趣,那么combineReducers 将确保它只接收该部分。但是如果它需要更多的状态,那么你可以应用这个特定的 reducer,让它接收整个状态。
整个应用程序最终将只有一个 reducer - 一个处理整个状态和所有操作的 reducer - 但您可能希望在某个时候将应用程序代码拆分为与主题相关的模块,所以编写更小的与主题相关的 reducer 更容易,并将它们组合成一个。 combineReducers 只是一个帮手,让您可以在需要时方便地进行操作。
- 更多文件会导致更多混乱和意外错误。
- 不必要的代码拆分。 ...
何时拆分代码由您决定。我喜欢将不相关的功能保存在不同的文件中。例如,如果我的 Web 应用程序有一个聊天模块,我可能会创建一个 chat 包并将所有与聊天相关的代码放入其中 - 一个视图、一组动作和理解这些动作的 reducer。
继续前进:
combineReducers 很有帮助,因为它非常适合可重复使用的应用程序。例如,我可以编写一个处理 cmets 的模块...其中一部分将是一个 reducer,例如:
const initialState = {
commentList: [], // list of { author, text, upvotes }
commentingAllowed: true,
}
function commentReducer(state, action) {
if (typeof state === 'undefined') {
return initialState;
}
switch (action.type) {
// ...
}
}
但我的应用程序的实际状态可能更复杂,例如:
{
currentArticle: {
title: "Some article",
published: "2017-04-05",
author: "someone",
comments: {
commentList: [],
commentingAllowed: true,
}
}
}
评论状态嵌套在currentArticle 下,但我的 cmets 应用程序(特别是 commentReducer 不了解文章的整个概念!所以我不希望它接收整个状态 - 它不会知道如何处理它。我希望这个 reducer 只接收与其 cmets 对应的状态部分。
请注意,我可以同时拥有多篇文章,也可能是其他可评论的内容。通过巧妙地组合减速器,您可以拥有 cmets 应用程序的多个“实例”,每个实例只处理自己的一小部分状态。这需要比 combineReducers 单独使用更智能的胶水代码,但它显示了一种情况,即 reducer 自然只需要应用程序状态的特定部分 - 关注点分离。