用户可以对n
项进行投票。有两种React状态:
>
vote
是用户对每个项目的投票数组。
const [votes, setVotes] = useState({});
voteChange
指示用户更改对任何项目的投票次数。
const[voteChanges,setVoteChanges]=useState(0);
我们在useEffect
中定义了一个数据库侦听器。当在数据库中添加/更改投票时,将调用侦听器。我们需要状态<code>投票</code>将每个新的投票与<code>中的前一个值进行比较,以决定是否增加<code>voteChanges</code>。然而,我们不能在useEffect
中将投票
定义为依赖项,否则我们将陷入无限循环。要访问投票
的当前值,我们使用其函数更新。在setVotes
的功能更新中调用setVoteChanges
可以吗?如果没有,为什么,你会如何解决这个问题?
useEffect(() => {
databaseListener((changes) => {
setVotes((oldVotes) => {
const oVotes = { ...oldVotes };
for (let change of changes) {
const itemId = change.id;
const newVote = change.vote;
if (oVotes[itemId] !== newVote) {
setVoteChanges(oldCount => oldCount + 1);
}
oVotes[itemId] = newVote;
}
return oVotes;
});
});
});
这是代码 https://codesandbox.io/s/react-tracking-vote-changes-x3jhwj?file=/src/App.js
因此,首先,您需要确保此处的useEffect
只运行一次,因为您不需要每次都注册到databaseListener
。其次,您需要记住状态更改将导致重新渲染的事实,因此最好在变量中计算voteChange
,然后应用一次。检查下面的代码段。
useEffect(() => {
databaseListener((changes) => {
let voteChanges = 0;
setVotes((oldVotes) => {
const oVotes = { ...oldVotes };
for (let change of changes) {
const itemId = change.id;
const newVote = change.vote;
if (oVotes[itemId] !== newVote) {
voteChanges++;
}
oVotes[itemId] = newVote;
}
return oVotes;
});
setVoteChanges(oldCount => oldCount + voteChanges); // rather than having to update it each time, just update it once because state changes can result in re-renders
});
}, []); // you just need this to run once to register the listener, so add []