在这个减速器组成示例的情况下,为什么我们不能只返回我们调用的减速器?这意味着,在todoApp
或ADD_TODO
的{{1}}缩减器中,我们使用的是另一个缩减器:TOGGLE_TODO
。我明白那个。但我不明白为什么我们不能将todos
中的案例设为
todoApp
vs我们在这里:
function todoApp(state = initialState, action) {
switch (action.type) {
case ADD_TODO:
case TOGGLE_TODO:
return todos(state.todos, action)
特别是因为todos reducer正在返回全新的状态对象,对吧?我们是不是仍然遵循redux规则而不是通过返回第二个reducer的结果来修改状态?
function todoApp(state = initialState, action) {
switch (action.type) {
case ADD_TODO:
case TOGGLE_TODO:
return Object.assign({}, state, {
todos: todos(state.todos, action)
})
答案 0 :(得分:3)
你问为什么这个
case TOGGLE_TODO:
return Object.assign({}, state, {
todos: todos(state.todos, action)
})
......不能只是这个......
case TOGGLE_TODO:
return todos(state.todos, action)
你必须注意你正在使用的reducer的特定上下文中的状态的形状
todo
的状态为[Todo]
- 其中[Todo]
是待办事项的数组
todoApp
的状态为{todos: [Todo]}
如果您要使用建议的代码
case TOGGLE_TODO:
return todos(state.todos, action)
知道todos
将返回[Todo]
,您将取代todoApp
州......
{todos: [Todo]}
...与
[Todo]
......这不是正确的形状。
所以如果形状相同,那就没关系,否则我不会修改状态,对吗? - Anna Garcia 25分钟前
正确,但他们在这种情况下使用Object.assign
的原因是一种前瞻性的最佳做法。
你可以做到
case TOGGLE_TODO:
return {todos: todos(state.todos, action)}
但是,有理由认为您的应用程序将具有其需要关注的其他“切片”状态 - 而不是只是 todos
。在这种情况下,TOGGLE_TODO
操作仅对todos
切片起作用。谨慎地更新todos
的方式不会破坏此上下文中的所有其他现有属性。
因此,假设我们的应用程序还有另外两个状态切片,foo
和bar
。如果我们这样做......
// where state = {foo: 1, bar: 2, todos: [ ... ]}
case TOGGLE_TODO:
return {todos: todos(state.todos, action)}
然后我们只返回{todos: ...}
- foo
和bar
属性/值已被删除!不好!</ p>
相反,我们必须小心保留其他状态条目,仅对我们打算修改的状态进行操作
// where state = {foo: 1, bar: 2, todos: [ ... ]}
case TOGGLE_TODO:
return Object.assign({}, state, {todos: todos(state.todos, action)})
现在我们将回来
{foo: 1, bar: 2, todos: newTodosArray}
这正是我们想要的 - 所有foo
,bar
和todos
属性仍处于todoApp
状态。
对象传播语法
有一项建议支持对象的扩展语法,这可以将Object.assign
示例简化为
case TOGGLE_TODO:
return {...state, todos: todos(state.todos, action)}
但是直到它进入ECMAScript,你将不得不使用transform-object-rest-spread
进行babelify答案 1 :(得分:0)
redux的主要概念是你永远不能直接修改状态,你必须返回一个新的状态。您提出的解决方案是修改当前状态,这是不允许的。
特别是因为todos reducer正在返回全新的状态 对象,对吗?1
这里的关键词是'新'。它必须是一个新的状态对象,而不是对当前对象的修改。