在egghead.io series on Redux的第16课中,在尝试Dan如何做之前,我尝试实现自己的combineReducers功能。我得到了以下内容。我试图对传入的子缩减器(for ... in
,todos
)使用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,
})
我的问题是:
reduce
,但出于教学原因,我该如何使用for ... in
模式来实现combineReducers? for ... in
对这些应用程序的适当性,如果它是一个糟糕的模式,它是什么使它如此?答案 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;
}
}