为什么第二个参数是[], 这个定时器还是会每秒执行一次呢?
3 个回答
第一:因为你依赖为空数组[],意味着不会有任何引起effect变化的因素,即触发rerender并不会再次进入effect,且只有等到组件销毁的时候才会clearInterval,即执行销毁函数
第二:因为依赖为空,然后你effect里面用了setInterval,意味着每秒会调用setReRender
第三:setReRender参数是回调函数,每次会+1,所以也就有了你所说的
发现每隔1s就render一次
综上:要只执行一次,直接将setInterval改为setTimeout,clearInterval改为clearTimeout不就好?
在React中,
useEffect
可以用来执行副作用操作,例如在组件挂载或卸载时执行某些操作,或在组件属性或状态变化时执行某些操作。第二个参数是一个依赖项数组,它用于指定在哪些依赖项变化时才需要重新执行effect。
如果依赖项数组为空,即
[]
,则effect只会在组件挂载时执行一次,相当于
componentDidMount
,并且在组件卸载时清除effect。所以,对于你的代码,setInterval只会在组件挂载时执行一次,并且每秒执行一次回调函数,同时也会在组件卸载时清除setInterval,因此它不会导致内存泄漏。
但是,由于在回调函数中更新了组件状态,这会触发组件重新渲染,因此每秒都会调用
useEffect
回调函数并再次设置定时器,导致定时器一直在运行,所以你会看到每秒都会有一次重新渲染。如果你只想在组件挂载时执行一次回调函数,而不是在每次重新渲染时执行,你可以将依赖项数组设置为
null
或
undefined
,这样回调函数将只在组件挂载时执行一次,而不会在每次重新渲染时执行。例如:
useEffect(() => {
const interval = setInterval(() => {
setReRender(count => count + 1);
}, 1000);
return () => clearInterval(interval);
}, null);
或者你可以使用
useRef
来存储定时器的引用,这样在每次重新渲染时不会重新创建定时器。例如:
const intervalRef = useRef(null);
useEffect(() => {
intervalRef.current = setInterval(() => {
setReRender(count => count + 1);
}, 1000);
return () => clearInterval(intervalRef.current);
}, []);
在
useEffect
中,第二个参数
[]
的作用是告诉React只有在组件挂载和卸载的时候才会运行该
useEffect
回调函数。所以在组件挂载时,
setInterval
会被执行,然后每隔1秒
setReRender
会被调用,触发组件重新渲染。由于
setInterval
在
useEffect
回调函数的返回值中被清除了,所以在组件卸载时,计时器也会被清除。但是,由于
setInterval
的执行是异步的,当组件重新渲染时,
setInterval
可能还未被清除,所以会继续执行,导致组件重新渲染。如果你想在组件重新渲染时清除计时器,可以在组件的
useEffect
回调函数中添加一个清除计时器的操作。
如果你想在组件重新渲染时清除计时器,可以添加一个监听组件重新渲染的
useEffect
回调函数,然后在该回调函数中清除计时器。修改后的代码如下所示:
useEffect(() => {
const interval = setInterval(() => {
setReRender(count => count + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
useEffect(() => {
return () => clearInterval(interval);
}, [reRender]);
在这个例子中,第一个
useEffect
回调函数仍然是在组件挂载和卸载时才会运行,用于创建计时器并清除计时器。而第二个
useEffect
回调函数会在组件重新渲染时运行,用于清除计时器。它的第二个参数是一个数组,包含了
reRender
变量,表示当
reRender
变量的值发生改变时,该
useEffect
回调函数会运行。所以当组件重新渲染时,第二个
useEffect
回调函数会运行,并清除计时器。当组件重新渲染时,第二个
useEffect
回调函数会运行,并清除之前创建的计时器,防止计时器继续执行。这样就可以保证计时器只在组件挂载时创建,并在组件卸载或重新渲染时被清除。完整代码如下所示:
import React, { useState, useEffect } from 'react';
function Timer() {
const [reRender, setReRender] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setReRender(count => count + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
useEffect(() => {
return () => clearInterval(interval);
}, [reRender]);
return (