【发布时间】:2021-03-21 07:39:47
【问题描述】:
我想澄清一下我对这里发生的事情的理解。任何能提高我目前理解的细节都将不胜感激。
function Timer() {
let [time, setTime] = useState(5);
useEffect(() => {
let timer = setInterval(() => {
setTime(time - 1);
}, 1000)
return () => clearInterval(timer);
}, );
return <div>{time}</div>
}
export default Timer
https://codesandbox.io/s/cranky-chaplygin-g1r0p
-
time正在初始化为5。 -
useEffect已读取。它的回调必须准备好稍后触发。 -
div被渲染。 -
useEffect的回调被执行。setInterval的回调准备触发。当然useEffect的return语句不会在这里触发,因为如果触发它会取消计时器(并且计时器确实有效)。 - 大约 1 秒后,
setInterval的回调触发将time的状态更改为 4。 - 现在一个状态已经改变,函数被重新执行。
time,一个新变量,被初始化为新的时间状态。 - 读取了一个新的
useEffect,它的回调准备好稍后触发。 (这是因为useEffect()没有第二个参数)。 - 组件函数的
return语句被执行。这有效地重新渲染了div。 - 在某些时候,前一个
useEffect的return语句会执行(这会禁用前一个useEffect中的timer)。我不确定何时会发生这种情况。 - “新”
useEffect的回调被执行。
【问题讨论】:
-
useEffect有一个依赖数组,如果你不使用它,useEffect 将在每次状态更改时被调用。对于像这样的计时器,将[]传递给你的依赖将停止计时器不断地被创造/毁灭。 PS:盲目地将[]传递给所有 useEffects 并不总是一个好主意,请确保还包括任何应该影响您的渲染的依赖项, -
谢谢@Keith,但这不是我要问的问题。我已经剥离了原始代码,并希望确保我对“生命周期”中发生的事情的理解是正确的。如果您对我的理解有任何 cmets,那会很有帮助
-
No.8,重新渲染是什么意思,只有在Props或State发生变化时才会重新渲染。你得到一个重新渲染,因为你改变了状态,仅此而已。
-
澄清一下,在本例中,您在每次渲染时创建一个间隔,请确保您了解此计数器为何有效,尽管这是一个非常糟糕的示例,但而不是你如何在 React 中创建计数器。
-
@tonitone120 在您的示例中使用
SetTimeout而不是SetInterval会更好,或者如果您确实使用SetInterval使用依赖项[],也可以使这更完整-证明,像计时器等异步的东西应该做一个安装检查,否则你最终可能会在一个未安装的组件上调用setState。
标签: javascript reactjs react-hooks