2017-02-27 39 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

相關問題