我处于这种状态
allVotes: [
{
id: "vote_1",
title: "How is your day?",
description: "Tell me: how has your day been so far?",
choices: [
{ id: "choice_1", title: "Good", count: 7 },
{ id: "choice_2", title: "Bad", count: 12 },
{ id: "choice_3", title: "Not sure yet", count: 1 },
],
},
{
id: "vote_2",
title: "Programming languages",
description: "What is your preferred language?",
choices: [
{ id: "choice_1", title: "JavaScript", count: 5 },
{ id: "choice_2", title: "Java", count: 9 },
{ id: "choice_3", title: "Plain english", count: 17 },
],
},
],
,并且需要更新计数。这可以(在控制器组件中)工作
registerVote(vote, choice) {
this.setState(prevState => {
return {
allVotes: prevState.allVotes.map(
pVote =>
pVote.id !== vote.id
? pVote
: {
...pVote,
choices: pVote.choices.map(
pChoice =>
pChoice.id !== choice.id
? pChoice
: {
...pChoice,
count: pChoice.count + 1,
},
),
},
),
};
});
}
但是它看起来很复杂,我不确定 如果这是正确的方法。有更好的方法吗?
答案 0 :(得分:2)
实际上,这是您要保持不变性的方法,但是可以通过使用一些辅助函数来简化它:
const change = (key, fn) => obj => ({ ...obj, [key]: fn(obj[key]) });
const changeOne = (filter, fn) => arr => arr.map(el => filter(el) ? fn(el) : el);
this.setState(change("allVotes", changeOne(v => v.id === vote.id, change("count", c => c + 1))));
答案 1 :(得分:2)
您可以将组件分解为较小的组件。说:形式,票数,票数。
class Vote extends React.Component {
increment = () => {
this.setState(prevState => ({
count: prevState.count + 1
}), this.onItemChange);
}
onItemChange = () => {
this.props.onItemChange(this.state, this.props.id);
}
}
class Votes extends React.Component {
onItemChangedCallback = (itemToUpdate, idToUpdate) => {
this.setState(prevState => ({
allVotes: prevState.allVotes.map(vote => vote.id === idToUpdate? {...itemToUpdate}: vote; )
}), this.onVotesChangeCallback);
}
onVotesChangeCallback = () => {
this.props.onVotesChange(this.state.allVotes)
}
render() {
return (<div>this.state.allVotes.map(vote => <Vote id={vote.id} key={vote.id} vote={vote} onItemChange={this.onItemChangedCallback} />)</div>);
}
}
此外,这意味着更多的类/组件符合“单一职责”原则:因此Votes
处理列表中的移动元素,删除并添加新的但不包括时间戳值,投票者数量或投票者列表的元素。 Vote
处理单个项目。等等。更好的测试,更易于阅读,更易于在不同上下文中重用。
[UPD]经过更多思考之后,我认为最好将唯一的id从投票传递到投票,而不是位置索引(以及key
道具建议)。然后使用它的id找出应该替换哪个collection的元素。相应地更新了代码段。
[UPD2]我猜Vote
可以是功能/无状态组件,但我最好将其保留为基于类的,以使想法更易于理解