【发布时间】:2017-05-07 13:34:07
【问题描述】:
在这个Redux: Colocating Selectors with Reducers Egghead 教程中,Dan Abramov 建议使用接受完整 状态树而不是状态切片的选择器来封装远离组件的状态知识。他认为这使得更改状态结构变得更容易,因为组件不知道它,我完全同意。
但是,他建议的方法是,对于对应于特定状态切片的每个选择器,我们在根 reducer 旁边再次定义它,以便它可以接受完整状态。当然,这种实现开销会破坏他试图实现的目标......简化未来更改状态结构的过程。
在一个有很多reducer 的大型应用程序中,每个reducer 都有很多选择器,如果我们在根reducer 文件中定义所有选择器,我们是否会不可避免地遇到命名冲突?直接从其相关的 reducer 导入选择器并传入全局状态而不是相应的状态切片有什么问题?例如
const todos = (state = [], action) => {
switch (action.type) {
case 'ADD_TODO':
return [...state, todo(undefined, action)];
case 'TOGGLE_TODO':
return state.map(t => todo(t, action));
default:
return state;
}
};
export default todos;
export const getVisibleTodos = (globalState, filter) => {
switch (filter) {
case 'all':
return globalState.todos;
case 'completed':
return globalState.todos.filter(t => t.completed);
case 'active':
return globalState.todos.filter(t => !t.completed);
default:
throw new Error(`Unknown filter: ${filter}.`);
}
};
这样做有什么缺点吗?
【问题讨论】:
-
是的,我刚刚观看了那个视频,我可以看到一旦应用程序开始增长,一个动作就拥有 3 个真实来源,这看起来很糟糕 - 很糟糕。从 jsx 文件中的这一操作,我们调用 reducer/index 文件,该文件现在具有对保存状态的 reducer 文件的引用。我不知道,这对我来说 - 似乎有很多开销,并且要实例化一个需要数据片段的方法,我们现在必须在 3 个不同的文件中感受到它的存在。现在,将其乘以 50 或 100……也许在像“todos”这样的非常基础的应用程序中,它很好。但它不是现实世界。
-
Redux 中的很多东西都是建议的最佳实践,但这并不一定意味着它们最适合所有情况或您的用例。我做事的方式和你一样:将选择器与它们对应的减速器放在一起。我认为这更有意义,因为访问状态部分的知识位于定义状态部分的函数旁边。不过,这真的是关于什么对你最有效,而且 Redux 社区中的许多人都认为这就是你应该追求的。
-
在大型应用程序中,我认为教程中提出的结构不再有效。您需要根据它们所针对的特定域对象来拆分您的减速器/选择器/操作。要回答您的问题,除了您在组件和特定 reducer 之间引入了很多依赖关系之外,没有任何缺点
-
我在datchley.name/scoped-selectors-for-redux-modules找到了一篇关于这个问题的好帖子
标签: javascript redux reducers