如何在使用React Hooks中的useEffect时清除setInterval?

23
我正在尝试创建一个加载组件,它会使用React中的setInterval每1000ms定期向div中添加一次句号。我正在尝试使用文档中描述的方法清理setInterval。

我正在尝试创建一个加载组件,它会使用React中的setInterval每1000ms定期向div中添加一次句号。我正在尝试使用文档中描述的方法清理setInterval。

https://reactjs.org/docs/hooks-effect.html#example-using-hooks-1

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

const Loading = () => {
    const [loadingStatus, setLoadingStatus] = useState('.')
    const [loop, setLoop] = useState()
    useEffect(() => {
        setLoop(setInterval(() => {
            console.log("loading")
            setLoadingStatus(loadingStatus + ".")
        }, 1000))

        return function cleanup() {
            console.log('cleaning up')
            clearInterval(loop)
        }
    }, [])
    return (<p>
        {`Loading ${loadingStatus}`}
    </p>)
}
export default Loading

然而,loadingStatus 变量只更新一次,即使组件停止挂载后 setInterval 循环也不会被清除。我是否需要使用类组件来解决?

1个回答

29

依赖项是 React 中指示何时运行 effect 的提示,即使我们设置了间隔并且没有提供任何依赖项 [],React 也不会知道我们希望运行它多次,因为在空的依赖项 [] 中没有任何变化。

为了获得所需的结果,我们需要思考何时想要运行 effect?

loadingStatus 改变时我们想要运行它,因此我们需要将 loadingStatus 添加为我们的依赖项,因为我们希望每次 loadingStatus 发生变化时都运行 effect。

我们有两个选择:

loadingStatus 添加为我们的依赖项。

const Loading = () => {
  const [loadingStatus, setLoadingStatus] = useState(".");
  const [loop, setLoop] = useState();

  useEffect(
    () => {
      setLoop(
        setInterval(() => {
          console.log("loading");
          setLoadingStatus(loadingStatus + ".");
        }, 1000)
      );

      return function cleanup() {
        console.log("cleaning up");
        clearInterval(loop);
      };
    },
    [loadingStatus]
  );

  return <p>{`Loading ${loadingStatus}`}</p>;
};
让我们的效果不知道我们使用了loadingStatus
const Loading = () => {
  const [loadingStatus, setLoadingStatus] = useState(".");

  useEffect(() => {
    const intervalId = setInterval(() => {
      setLoadingStatus(ls => ls + ".");
    }, 1000);

    return () => clearInterval(intervalId);
  }, []);

  return <p>{`Loading ${loadingStatus}`}</p>;
};

在这里阅读更多 => a-complete-guide-to-useeffect


为什么你的 useEffect 不将“loop”作为依赖项,即使它在清理期间使用它。当然,将其添加到依赖项中会使其不断地再次触发。 - GeorgeButter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接