我的reducer默认返回(来自教程):
return [
{
id: 1,
first: "Bucky",
last: "Roberts",
age: 71,
description: "Bucky is a React developer and YouTuber",
thumbnail: "http://i.imgur.com/7yUvePI.jpg"
},
{
id: 2,
first: "Joby",
last: "Wasilenko",
age: 27,
description: "Joby loves the Packers, cheese, and turtles.",
thumbnail: "http://i.imgur.com/52xRlm8.png"
},
{
id: 3,
first: "Madison",
last: "Williams",
age: 24,
description: "Madi likes her dog but it is really annoying.",
thumbnail: "http://i.imgur.com/4EMtxHB.png"
}
]
}
我现在希望能够从此“列表”中删除用户条目。所以我继续构建了一个删除用户操作创建者等,所以除了上面的数据之外,现在还有这个代码:
switch (action.type) {
case 'USER_DELETED':
console.log("Hello from reducer-users");
let newState = Object.assign({}, state, );
// console.log(newState == state);
// console.log(newState.users == state.users)
// delete newState.users;
return newState;
break;
}
这个想法是,如果有人点击“删除用户”,则会调用此函数并返回一个新状态,并删除相应的用户。它也可以在调用函数的意义上工作(显示console.log)。但是,我现在不确定如何从此列表中删除用户?我知道我需要复制当前状态,然后从副本中删除用户,&然后返回副本,使其成为新状态。它是否正确?如果是这样,我不知道究竟是怎么回事。如果我尝试执行上面所写的内容,那就是s.b.在stackoverflow上写道,我收到一个错误:
user-list.js?1cc2:11 Uncaught TypeError:this.props.users.map不是 function(...)renderList @ user-list.js?1cc2:11render @ ?d41d:33(匿名函数)@ ReactCompositeComponent.js?cd59:793measureLifeCyclePerf @ ?ReactCompositeComponent.js CD59:74_renderValidatedComponentWithoutOwnerOrContext @ ReactCompositeComponent.js?cd59:792_renderValidatedComponent @ ReactCompositeComponent.js?cd59:819_updateRenderedComponent @ ReactCompositeComponent.js?cd59:743_performComponentUpdate @ ReactCompositeComponent.js?cd59:721updateComponent @ ReactCompositeComponent.js?cd59:642receiveComponent @ ReactCompositeComponent.js?cd59:544receiveComponent @ ReactReconciler.js?6bfa:126_updateRenderedComponent @ ReactCompositeComponent.js?cd59:751_performComponentUpdate @ ReactCompositeComponent.js?cd59:721updateComponent @ ReactCompositeComponent.js?cd59:642performUpdateIfNecessary @ ReactCompositeComponent.js?cd59:558performUpdateIfNecessary @ ReactReconciler.js?6bfa:158runBatchedUpdates @ ReactUpdates.js?ce09:151perform @Transaction.js?6dff:138perform @ Transaction.js?6dff:138perform @ ReactUpdates.js?ce09:90flushBatchedUpdates @ ReactUpdates.js?ce09:173closeAll @Transaction.js?6dff:204perform @ Transaction.js?6dff:151batchedUpdates @ ReactDefaultBatchingStrategy.js?ef70:63batchedUpdates @ ReactUpdates.js?ce09:98dispatchEvent @ ReactEventListener.js?2365:150
这是整个Redurs文件:
/*
* The users reducer will always return an array of users no matter what
* You need to return something, so if there are no users then just return an empty array
* */
export default function (state = null, action) {
switch (action.type) {
case 'USER_DELETED':
console.log("Hello from reducer-users");
//let newState = Object.assign([{}], state);
// return newState;
return state.filter(user => user.id !== action.userIdToDelete);
console.log("UNTIL HERE");
// console.log(newState.users == state.users)
// delete newState.users;
// return ([{
// id: 5,
// first: "Bucky",
// last: "Roberts",
// age: 71,
// description: "Bucky is a React developer and YouTuber",
// thumbnail: "http://i.imgur.com/7yUvePI.jpg"
// }]);
break;
console.log("UNTIL HERE2222");
}
return [
{
id: 1,
first: "Bucky",
last: "Roberts",
age: 71,
description: "Bucky is a React developer and YouTuber",
thumbnail: "http://i.imgur.com/7yUvePI.jpg"
},
{
id: 2,
first: "Joby",
last: "Wasilenko",
age: 27,
description: "Joby loves the Packers, cheese, and turtles.",
thumbnail: "http://i.imgur.com/52xRlm8.png"
},
{
id: 3,
first: "Madison",
last: "Williams",
age: 24,
description: "Madi likes her dog but it is really annoying.",
thumbnail: "http://i.imgur.com/4EMtxHB.png"
}
]
}
答案 0 :(得分:5)
你说你的减速器应该返回一个新的状态副本,而不是改变当前状态。这种方法有一些很好的好处(见这里:http://redux.js.org/docs/Glossary.html#reducer)
假设此reducer管理的状态是一个数组,要从列表中删除用户,您可以执行以下操作:
switch (action.type) {
case 'USER_DELETED':
return state.filter(user => user.id !== action.userIdToDelete);
}
关键是Array.filter返回一个新的数组,该数组将回调应用于每个元素,决定保留/过滤哪一个,它不会改变原始数组。查看此处的文档https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
您可能会尝试使用Array.splice(https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/splice),但在这种情况下这是错误的,因为splice
“通过删除现有元素和/或添加来更改数组的内容新元素。“,所以它确实改变了原来的元素。
请注意,您需要在动作有效负载中传递userIdToDelete
。
此外,由于您已使用break
,因此不需要return
。
至于你发布错误的确切原因,问题是你的reducer目前正在返回一个对象而不是一个数组:let newState = Object.assign({}, state, );
然后,在组件的某个地方,你正在从状态读取并且您尝试在状态上调用map
,这不再是数组(因此没有为map
定义this.props.users
方法
另一个建议:
我真的建议你开始在reducers中使用普通的Js,总是要小心那些改变对象的方法。 在你知道自己在做什么之后,有时在Js中使用不可变数据结构可能会很笨拙,所以你可以开始考虑使用这些库来减轻更复杂场景的痛苦(但只有在你确实需要时),按复杂程度排序(显然在我看来):