【问题标题】:How can I start / stop setInterval?如何启动/停止 setInterval?
【发布时间】:2022-12-11 00:55:41
【问题描述】:

我尝试了不同的方法,但它不起作用。

[...]
  const [automatic, setAutomatic] = useState(false);

[...]
  var startAuto;

  useEffect(() => {
    if (!automatic) {
      console.log("stop");
      clearInterval(startAuto);
    } else {
      startAuto = setInterval(() => {
        changeQuestion("+");
      }, 5 * 1000);
    }
  }, [automatic]);

[...]
        <Button
          onPress={() => setAutomatic(!automatic)}
          title="turn on/off"
        />
[...]

当我将 setTimeout 放在 useEffect 之外时它会起作用,这样:

setTimeout(() => { clearInterval(startAuto); alert('stop'); }, 10000);

但我想要一个按钮来启动/停止

【问题讨论】:

    标签: javascript react-native react-hooks setinterval


    【解决方案1】:

    您的 var startAuto; 在每次渲染时都会重新声明,并且由于更改状态会导致重新渲染,因此它永远不会保留对永远不会被清除的间隔的引用。

    使用useEffect清理功能清除间隔。每当automatic发生变化时,它就会调用cleanup(如果之前的调用返回),如果automatictrue,它就会创建一个新的间隔循环,并返回一个新的当前间隔的清理函数。

    useEffect(() => {
      if(!automatic) return;
      
      const startAuto = setInterval(() => {
        changeQuestion("+");
      }, 5 * 1000);
    
      return () => {
        clearInterval(startAuto);
      };
    }, [automatic]);
    

    工作示例:

    const { useState, useEffect } = React;
    
    const Demo = () => {
      const [automatic, setAutomatic] = useState(false);
      const [question, changeQuestion] = useState(0);
      
      useEffect(() => {
        if(!automatic) return;
        
        const startAuto = setInterval(() => {
          changeQuestion(q => q + 1);
        }, 5 * 100);
    
        return () => {
          clearInterval(startAuto);
        };
      }, [automatic]);
    
      return (
        <div>
          <button
            onClick={() => setAutomatic(!automatic)}
          >
            turn {automatic ? 'off' : 'on'}
          </button>
          
          <p>{question}</p>
        </div>
      );
    }
    
    ReactDOM
      .createRoot(root)
      .render(<Demo />);
    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    
    <div id="root"></div>

    【讨论】:

    • 刚刚救了我的一天,谢谢!
    • 别客气 :)
    【解决方案2】:

    例如,您可以检查并使用这个钩子:

    https://usehooks-ts.com/react-hook/use-interval

    export default function Component() {
      // The counter
      const [count, setCount] = useState<number>(0)
      // Dynamic delay
      const [delay, setDelay] = useState<number>(1000)
      // ON/OFF
      const [isPlaying, setPlaying] = useState<boolean>(false)
    
      useInterval(
        () => {
          // Your custom logic here
          setCount(count + 1)
        },
        // Delay in milliseconds or null to stop it
        isPlaying ? delay : null,
      )
    
      const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
        setDelay(Number(event.target.value))
      }
    
      return (
        <>
          <h1>{count}</h1>
          <button onClick={() => setPlaying(!isPlaying)}>
            {isPlaying ? 'pause' : 'play'}
          </button>
          <p>
            <label htmlFor="delay">Delay: </label>
            <input
              type="number"
              name="delay"
              onChange={handleChange}
              value={delay}
            />
          </p>
        </>
      )
    }
    

    【讨论】:

      猜你喜欢
      • 2012-01-22
      • 1970-01-01
      • 1970-01-01
      • 2020-08-17
      • 1970-01-01
      • 2019-09-21
      • 2010-12-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多