2017-02-27 70 views
0

在这个减速机组成的例子中,为什么我们不能只返回我们正在调用的减速机?意思是在todoApp减速机的情况下ADD_TODOTOGGLE_TODO我们使用的是其他减速机:todos。我明白那个。但我不明白为什么我们不能只是设置的情况下在todoApp作为Reducer组成 - 为什么我们需要重新分配todos与Object.assign()为什么不只是调用其他reducer?

function todoApp(state = initialState, action) { 
    switch (action.type) { 
    case ADD_TODO: 
    case TOGGLE_TODO: 
     return todos(state.todos, action) 

VS我们这里:

function todoApp(state = initialState, action) { 
    switch (action.type) { 
    case ADD_TODO: 
    case TOGGLE_TODO: 
     return Object.assign({}, state, { 
     todos: todos(state.todos, action) 
     }) 

特别是自待办事项减速器返回焕发出新的状态对象, 对?我们是不是仍然遵循redux规则,而不是通过返回第二个reducer的结果来修改状态?

function todos(state = [], action) { 
    switch (action.type) { 
    case ADD_TODO: 
     return [ 
     ...state, 
     { 
      text: action.text, 
      completed: false 
     } 
     ] 
    case TOGGLE_TODO: 
     return state.map((todo, index) => { 
     if (index === action.index) { 
      return Object.assign({}, todo, { 
      completed: !todo.completed 
      }) 
     } 
     return todo 
     }) 
    default: 
     return state 
    } 
} 

function todoApp(state = initialState, action) { 
    switch (action.type) { 
    case SET_VISIBILITY_FILTER: 
     return Object.assign({}, state, { 
     visibilityFilter: action.filter 
     }) 
    case ADD_TODO: 
    case TOGGLE_TODO: 
     return Object.assign({}, state, { 
     todos: todos(state.todos, action) 
     }) 
    default: 
     return state 
    } 
} 

回答

3

你问为什么这

case TOGGLE_TODO: 
    return Object.assign({}, state, { 
    todos: todos(state.todos, action) 
    }) 

...不能只是这个...

case TOGGLE_TODO: 
    return todos(state.todos, action) 

你必须要留意的状态的形状的您正在使用的减速器的具体环境

  • todo拥有[Todo]状态形状 - 其中[Todo]是待办事项

  • todoApp{todos: [Todo]}

状态形状的阵列如果你使用你的推荐代码

case TOGGLE_TODO: 
    return todos(state.todos, action) 

知道todos将返回[Todo],您将替换todoApp s泰特...

{todos: [Todo]} 

...与

[Todo] 

...这是不正确的形状。


因此,如果形状是相同的,这将是好的,我不会以其他方式修改状态,是否正确? - 安娜加西亚25分钟前

正确,但他们在这种情况下使用Object.assign的原因是一种前瞻性思考的最佳做法。

你可以只是做

case TOGGLE_TODO: 
    return {todos: todos(state.todos, action)} 

但是,这是合理的认为你的应用程序将有其他国家的“切片”,它需要关心 - 不只是todos。在这种情况下,TOGGLE_TODO操作仅对todos切片起作用。注意更新todos的方式不能在此上下文中打破所有其他现有属性。

假设我们的应用程序有两个其他切片状态,foobar。如果我们这样做......

// where state = {foo: 1, bar: 2, todos: [ ... ]} 
case TOGGLE_TODO: 
    return {todos: todos(state.todos, action)} 

那么我们只返回{todos: ...} - 的foobar属性/值已经下降了!不好!

相反,我们必须要小心保护其他国家的条目和操作上,我们打算状态修改

// 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,bartodos属性仍处于todoApp状态。


对象传播语法

有支持传播语法对象的建议,这可以简化Object.assign例子

case TOGGLE_TODO: 
    return {...state, todos: todos(state.todos, action)} 

但直到这使得它成为ECMAScript中,你将不得不使用babelify它transform-object-rest-spread

+0

所以如果形状相同,这将是好的,我不会修改状态,否则,是正确的? – Turnipdabeets

+0

@AnnaGarcia更新了我的答案以解决您的问题 – naomik

0

redux的主要概念是,你永远不能直接修改状态,你必须返回一个新的状态。您提出的解决方案将修改当前状态,这是不允许的。

特别是自待办事项减速器返回焕发出新的状态 对象,对不对?1

他们关键字这里是“新”。它必须是一个新的状态对象,而不是当前对象的修改。

+0

但它不是它返回一个新的状态,而不是修改我如果我们让第二个减速器接管这里?它将如何修改呢? – Turnipdabeets

相关问题