2016-03-05 62 views
1

egghead.io series on Redux的第16課中,我試圖實現我自己的combineReducers功能,然後再看看Dan是如何做到的。我得到了以下。我試圖用傳遞在子減速器(todosvisibilityFilterfor ... in像這樣使用```for ... in```實現combineReader?

const combineReducers = (reducers) => { 
    return (state,action) => { 
    let temp = {}; 
    for (let i in reducers) { 
     temp[i] = reducers[i](state,action) 
    } 
    return temp; 

    } 
} 

這是行不通的。當我用期望的庫進行測試時,我在控制檯中收到以下錯誤。奇怪的是,如果我沒有弄錯,看起來減速機todos的調用狀態已經嵌套到visibilityFilter減速機的調用中。這很奇怪,因爲我的代碼顯示它們是返回對象中明顯分離的字段。

Uncaught Error: Expected { todos: [ { completed: false, id: 1, text: 'Go shopping' } ], visibilityFilter: { todos: [ { completed: false, id: 0, text: 'Learn Redux' } ], visibilityFilter: 'SHOW_ALL' } } to equal { todos: [ { completed: false, id: 0, text: 'Learn Redux' }, { completed: false, id: 1, text: 'Go shopping' } ], visibilityFilter: 'SHOW_ALL' }

我的測試代碼

const testTodoApp =() => { 
    const stateBefore = { 
    todos: [{id: 0, text:'Learn Redux', completed: false}], 
    visibilityFilter: 'SHOW_ALL', 
    }; 

    // action is an object. with a defined type property. 
    const action = { 
    type: 'ADD_TODO', 
    id: 1, 
    text: 'Go shopping', 
    }; 

    const stateAfter = { 
    todos: [{id: 0, text:'Learn Redux', completed: false}, 
      {id: 1, text:'Go shopping', completed: false}, 
      ], 
    visibilityFilter: 'SHOW_ALL', 
    }; 

    deepFreeze(stateBefore); 
    deepFreeze(action); 

    expect(
    todoApp(stateBefore, action) 
).toEqual(stateAfter); 
    console.log("Test passed: todoApp") 

} 

testTodoApp(); 

如果我用內置的combineReducers此測試將通過。 是子減速器和來電combineReducers如下:

const todo = (state = {} ,action) => { 
    switch (action.type) { 

    case 'ADD_TODO': 
    return { 
     id: action.id, text: action.text, completed: false, 
    }; 

    case 'TOGGLE_TODO': 
    if (state.id !== action.id) { 
     return state; 
    } 
    return { 
     ...state, completed: !state.completed, 
    }; 

    default: 
    return state; 

    } 

} 
const todos = (state=[], action) =>{ 

    switch (action.type) { 
    case 'ADD_TODO': 
    console.log('ADD_TODO switch selected') 
    return [ 
     ...state, 
     todo(undefined,action), 
    ]; 

    case 'TOGGLE_TODO': 
    console.log('TOGGLE_TODO switch selected') 

    return state.map(t => todo(t, action)) 

    default: 
    console.log('default switch selected') 
    return state; 
    } 
} 

const visibilityFilter = (
    state = 'SHOW_ALL', 
    action 
) => { 
    switch (action.type) { 
    case 'SET_VISIBILITY_FILTER': 
     return action.filter; 
    default: 
     return state; 
    } 
} 


const todoApp = combineReducers({ 
    todos, 
    visibilityFilter, 
}) 

我的問題是:

  1. 那是什麼在我的代碼,其他內造成一個減速的這種嵌套?
  2. 我知道丹用reduce代替,但教學起見,我怎麼能去有關使用for ... in模式來實現combineReducers?
  3. 之後,可以請你在使用for ... in此類應用的適當性發表意見,如果它是一個糟糕的模式,它是什麼使得它如此?

回答

3

我剛剛意識到todos減速機和減速visibilityFilter必須通過對應於他們鍵,而不是整個組合狀態的組合狀態的一部分。所以工作代碼應該看起來像這樣,我在第五行添加了一個對象訪問器到狀態的相應部分。

const combineReducers = (reducers) => { 
    return (state,action) => { 
    let temp = {}; 
    for (let i in reducers) { 
     temp[i] = reducers[i](state[i],action) 
    } 
    return temp; 

    } 
}