简体   繁体   English

React useEffect:如何清除间隔?

[英]React useEffect: how to clearInterval?

I made a count down button.我做了一个倒计时按钮。

How could I clearInterval when the button will be unmounted?当按钮被卸载时,我怎么能clearInterval (like componentWillUnmount ) (比如componentWillUnmount

const CooldownButton = ({
  cooldown,
  ...props
}) => {
  const defaultClasses = useStyles();

  const [count, setCount] = useState(cooldown);
  const [timer, setTimer] = useState(null);

  useEffect(() => {
    if (count > 0 && !timer) {
      setTimer(
        setInterval(() => {
          if (count > 0) {
            setCount((prevState) => prevState - 1);
          }
          if (count === 0) {
            clearInterval(timer);
            setTimer(null);
          }
        }, 1000)
      );
    }
  }, [count, timer]);

  useUpdateEffect(() => {
    setCount(cooldown);
  }, [cooldown]);

  return (
    // ...
        <Typography
          size={24}
          className={clsx(defaultClasses.counter, classes?.counter)}
          {...counterProps}
        >
          {`${new Date(count * 1000)
            .toISOString()
            .substr(...(count >= 3600 ? [11, 8] : [14, 5]))}`}
        </Typography>
    // ...
  );
};

This will cause an infinite render:这将导致无限渲染:

  useEffect(() => {
    if (count > 0 && !timer) {
      // ...
    }
    return () => {
      clearInterval(timer);
      setTimer(null);
      
    }
  }, [count, timer]);

You are adding setTimer in return and at the same time you are adding timer variable in dependency array which will cause infinite rendering.您正在添加 setTimer 作为回报,同时您在依赖数组中添加计时器变量,这将导致无限渲染。 Because this useEffect will trigger whenever there is change in either count or timer.因为只要计数或计时器发生变化,就会触发此 useEffect。

In your case you are changing timer in useEffect itself which is causing infinite rendering.在您的情况下,您正在更改 useEffect 本身的计时器,这会导致无限渲染。 So, remove timer from dependency array (or remove setTimer function in case you don't need it) and try!因此,从依赖项数组中删除定时器(或者删除 setTimer function 以防你不需要它)并尝试!

 useEffect(() => {
    if (count > 0 && !timer) {
      // ...
    }
    return () => {
      clearInterval(timer);
      setTimer(null);
      
    }
  }, [count]);

if just wanner auto countdown, do not need setInterval,如果只是想自动倒计时,不需要setInterval,
when count changed, useEffect will run当计数改变时,useEffect 将运行

  const [count, setCount] = useState(cooldown);


  useEffect(() => {
    if (count > 0) {
       const timer = setTimeout(()=> {
          setCount(count - 1);
       }, 1000);
       return ()=> clearTimeout(timer);
    }
  }, [count, timer]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM