在 useEffect 中反应 setInterval

React setInterval inside useEffect

我在 React 中创建了一个非常基本的间隔。

import React, {useState, useEffect} from 'react';

const Loading2 = () => {
    const [percentage, setPercentage] = useState(0);

    useEffect(() => {
        const timer = setInterval(() => {
            setPercentage((prevPerc) => {
                if(percentage === 99)
                    return 0
                return prevPerc+1
            })
        }, 1000);
        return () => clearInterval(timer);
    }, [percentage])

    return (
        <div>
            <span>{percentage}%</span>
        </div>
    )
}

export default Loading2;

起初,我在我的 useEffect 中没有使用 return () => clearInterval(timer);,但没有成功。有谁知道为什么我需要 return 一个清理间隔的函数?另外,为什么它需要是一个函数,而不仅仅是 clearInterval(timer)?

谢谢

useEffect 的工作方式是:在任何渲染之后执行 useEffect 函数之前,它会执行上次 returned 的函数 useEffect被称为。如果您 return 像这样: return clearInterval(timer); 您已经执行了 clearInterval 函数 - 它不会等到下一次渲染时才执行。

对于 clearInterval,我不确定你所说的无效是什么意思,但我的猜测是它递增的数字不一致,并且每秒都在递增。这是因为每次设置状态时,组件都会重新渲染,生成一个新的间隔,但旧的间隔仍然存在,因此它会不断递增相同的值。这导致每次重新渲染你都有另一个递增函数。

关于为什么 useEffect 必须 return 一个函数,这里引用 reactjs.org:

Often, effects create resources that need to be cleaned up before the component leaves the screen, such as a subscription or timer ID. To do this, the function passed to useEffect may return a clean-up function ... The clean-up function runs before the component is removed from the UI to prevent memory leaks...

所以 useEffect 的实现需要 return 是一个被调用的函数。

React 在组件卸载时执行清理。 useEffect hook 的构建方式是,如果我们 return 方法中的一个函数,它会在组件卸载时执行。效果 运行 为每个渲染而不仅仅是一次。 useEffect 的清理在下一次渲染后 运行 秒,在下一次 useEffect 之前。.

The clean-up function runs before the component is removed from the UI to prevent memory leaks. Additionally, if a component renders multiple times (as they typically do), the previous effect is cleaned up before executing the next effect.

useEffect(() => {
  // This is the effect itself.
  return () => {
    // This is its cleanup.
  };
});

UseEffect 做 2 个工作。 class 组件中的 componentDidmountcomponentWillUnmount 事件。 useEffect中的第一个函数是componentDidmount,最后返回的函数是componentWillUnmount。

在您的代码中,您正在设置 percentage,这将触发组件重新呈现。如果您在组件中添加 console.log() ,您可以看到它一直在重新渲染。任何状态或道具更改都会触发重新渲染。

没有你的 clearInterval() 新的 setIntervals 被创建并触发了一个疯狂的 运行 setInterval。由于您现在正在清除卸载的间隔,因此每次都会创建一个新的 setInterval 并且您的状态仍然由 React 维护。您的组件仍然会随着您的状态更新而不断重新呈现。