我有以下React组件:App.tsx:
function App() {
const [countdownTimers, setCountdownTimers] = React.useState<
Map<number, number>
>(new Map([[1, 60]]));
useEffect(() => {
const timeoutId = setInterval(() => {
setCountdownTimers((prevState) => {
console.log(prevState);
for (const [timerKey, timer] of prevState) {
prevState.set(timerKey, timer - 1);
}
return new Map(prevState);
});
}, 1000);
return () => {
clearInterval(timeoutId);
};
}, []);
return <>{countdownTimers.get(1)}</>;
};
index.tsx
<React.StrictMode>
<App />
</React.StrictMode>
上面代码应该每秒从Map
中所有值中减去1
但是由于StrictMode
,它减去了2
删除<React.StrictMode>
解决了这个问题,但是我想了解为什么StrictMode
只有在Map
情况下才会这样
你能告诉我为什么是这样吗?
2条答案
按热度按时间mspsb9vt1#
在strict mode中,状态更新器函数被调用两次,以尝试检测可能的错误。
这里的代码确实有一个值得商榷的bug --您正在 * 改变 * Map中的现有状态:
虽然在返回时创建了一个新的Map,但仍然调用了
prevState.set
--改变它。这意味着(严格)状态更新程序第二次运行时,它看到的Map(第二次在prevState
中)已经将其值减少了一次。不要改变现有的Map,而是立即创建新的Map,并且只更改该新Map。
第一次
evrscar22#
发生这种情况是因为React strict模式,它与
Map
数据结构没有任何关系。严格模式不能自动检测副作用,但它可以通过使副作用更具有确定性来帮助你发现它们。这可以通过有意地双重调用以下函数来实现:
*状态更新程序函数(setState的第一个参数)
实际上,传递给
setCountdownTimers
setter的回调函数被调用了两次,因此减去了2
而不是1
。