使用```for ... in```实现combineReducers?

时间:2016-03-05 10:49:45

标签: javascript redux

egghead.io series on Redux的第16课中,在尝试Dan如何做之前,我尝试实现自己的combineReducers功能。我得到了以下内容。我试图对传入的子缩减器(for ... intodos)使用visibilityFilter

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

  }
}

这不起作用。当我使用expect库测试它时,我在控制台中收到以下错误。奇怪的是,如果我没有弄错的话,看起来调用todos减速器的状态已嵌套到visibilityFilter减速器的调用中。这很奇怪,因为我的代码显示它们在返回的对象中是明显不同的字段。

  

未捕获错误:预期{todos:[{completed:false,id:1,text:   '去购物' }],visibilityFilter:{todos:[{completed:false,   id:0,text:' Learn Redux' }],visibilityFilter:' SHOW_ALL' } } 至   相等{todos:[{completed:false,id:0,text:' Learn Redux' },{   完成:false,id:1,text:'去购物' }],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. 我的代码中是什么导致一个reducer嵌套在另一个中呢?
  2. 我意识到Dan使用了reduce,但出于教学原因,我该如何使用for ... in模式来实现combineReducers?
  3. 在那之后,你能否评论一下使用for ... in对这些应用程序的适当性,如果它是一个糟糕的模式,它是什么使它如此?

1 个答案:

答案 0 :(得分:3)

我刚刚意识到todos reducer和visibilityFilter reducers必须传递与键对应的组合状态的一部分,而不是整个组合状态。所以工作代码应该是这样的,我在第5行的状态的相应部分添加了一个对象访问器。

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

  }
}