如何解决使用setInterval时,React渲染不实际更改状态
我将分两步介绍我的问题,两者的代码块都稍有不同。
步骤1:
下面,我们有一个React应用程序,该应用程序每两秒钟渲染一次,因此使浏览器将 render 打印到控制台。如果用户按任意键,则渲染将停止,从而停止控制台打印。请暂时忽略注释掉的行。
import { useState,useEffect,useRef } from 'react';
function App() {
const [number,setUpdate] = useState(0);
const [isPaused,setIsPaused] = useState(false);
const intervalRef = useRef(undefined);
useEffect(() => {
intervalRef.current = setInterval(() => setUpdate(prevNumber => ++prevNumber),2000);
window.addEventListener('keydown',handleKeyDown);
},[]);
const handleKeyDown = () => {
clearInterval(intervalRef.current);
console.log('console log here');
// setIsPaused(isPaused);
};
console.log('render');
return null;
};
export default App;
上面发生的事情是,我让组件渲染了五次,然后按下了一个键以停止渲染组件。
第2步:
在第2步中,除了不注释掉在 handleKeyDown 中设置的状态之外,我们使用了完全相同的应用程序。
const handleKeyDown = () => {
clearInterval(intervalRef.current);
console.log('console log here');
// This is no longer commented out. Why does it cause a new render?
setIsPaused(isPaused);
};
同样,在按下键后,我让组件渲染了五次。但是现在,即使状态不应该更改,也有一个额外的渲染(因为状态实际上没有发生变化,因为我们设置了与状态中相同的值),方法是 setIsPaused(isPaused)。
我很难理解在步骤2中导致额外渲染的原因是什么?也许这很明显?
如果我注释掉由setInterval运行的其他状态更改,则setIsPaused(isPaused)永远不会导致新的渲染。
解决方法
这是一个已知的怪癖,请参阅#17474。这是新的并发模式引入的副作用。组件功能确实已重新运行,但DOM将保持不变。
我还发现有人张贴this interesting example。您可以使用代码尝试使用exp。组件函数包含类似<div>{Math.random()}</div>
之类的内容,尽管在函数的额外重新运行中随机数确实发生了变化,但是如果状态没有变化,它将不会反映在DOM上。
结论。您通常可以认为这种副作用是无害的。
,更新的状态从未手段DOM将重新呈现,̶你是对̶̶s̶e̶t̶I̶s̶P̶a̶u̶s̶e̶d̶(̶i̶s̶P̶a̶u̶s̶e̶d̶)̶
̶不会重新呈现DOM中,̶但将设置状态,并给你更新̶v̶a̶l̶u̶e̶.̶̶(我正在考虑{o {n̶l̶y̶̶s̶t̶a̶t̶e̶̶w̶i̶t̶h̶̶f̶i̶e̶l̶d̶̶̶i̶s̶P̶a̶u̶s̶e̶d̶
̶̶n̶o̶t̶h̶i̶n̶g̶̶e̶l̶s̶e̶)̶
更新:在阅读接受的答案之前,我确实知道此行为存在。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。