假设我想拥有以下状态结构:
{
deep: { ... },
foo: 0,
bar: 0,
str: ''
}
deep
可能很复杂,所以我想为它提取专用的reducer
const deepReducer = (state = {}, action) => { ... }
对于其余部分(foo,bar和str),只需使用另一个reducer,因为它们非常简单
const initialState = { foo: 0, bar: 0, str: '' } // May also need to add deep here
const defaultReducer = (state = initialState, action) => { ... }
但是这个结构似乎不起作用,如果使用combineReducers将其他reducers组合,那么结构将变为:
{
deep: { ... },
others: {
foo: 0,
bar: 0,
str: '',
}
}
但我不想把它们分组,因为他们的关系并不那么强大。
是否有可能在2个减速器中实现 ?或者唯一的解决方案是为每个州(foo,bar和str)创建专用的reducer?
答案 0 :(得分:1)
我觉得你应该先解决国家管理问题。然后,适当地拆分减速器会更容易。
TLDR 让您的Reducer尽可能简单,并使用状态规范化和选择器的组合,以确保您不会不必要地使您的Reducer复杂化。
州管理
正如文档所述
在顶级对象中组织数据的最常用方法是进一步将数据划分为子树,其中每个顶级键代表相关数据的某些“域”或“切片”。
首先,了解整个应用程序实际上只有一个减速器功能非常重要
状态树中的每个叶子(数据切片)都应该有自己的专用reducer。这是因为每个叶子代表分组数据的给定域。将此状态视为数据库。每个叶子代表一个分组数据表。
州规范化
你说你的州有一个深层嵌套的对象。
{
deep: { ... },
foo: 0,
bar: 0,
str: ''
}
而不是担心如何围绕这种状态形状构建缩减器,而是在第一种情况下尝试简化状态树。
如果规范化状态,这将降低状态对象中的嵌套级别。因此,减速器不必处理深层次的嵌套,因此更简单。
请记住,编码简单就是美。
<强>选择器强>
您的州包含应用程序中数据的最小表示。
如果你尽了最大的努力,你的状态中有一个深度嵌套(复杂)的对象,那么你就会使用你的选择器。如果您不使用选择器,那么您的Reducer将需要知道如何从状态中提取信息。这将为减速器添加不必要的逻辑,并使它们膨胀,从而破坏我们的应用程序模块化。
通过使用选择器,我们可以以模块化方式从我们的状态compute derived data,因为选择器可以重复使用和组合。
我们如何使用选择器?
使用我们州的类比作为前端数据库。选择器代表我们提取数据的查询。
选择器示例
来自文档的此示例使用流行的reselect库来创建选择器。 在这个例子中,从我们的状态计算的派生数据是实际可见的待办事项。过滤后的列表来自我们所有待办事项列表和当前可见性过滤器列表,可以设置为all,none或enabled。
const getKeyword = (state) => state.keyword
const getVisibleTodosFilteredByKeyword = createSelector(
[ getVisibleTodos, getKeyword ],
(visibleTodos, keyword) => visibleTodos.filter(
todo => todo.text.indexOf(keyword) > -1
)
)
如果我们没有执行此todo过滤操作,那么我们必须将过滤后的待办事项存储在状态中,并在每次可见性过滤器更改时更新stae。