如何使用React钩子重置setInterval函数

时间:2019-07-09 11:55:51

标签: javascript reactjs react-hooks

我正在使用here的Dan Abramov写的useInterval钩子

如何重置计数器?例如点击按钮?

codesandbox上的代码

function Counter() {
  const [count, setCount] = useState(0);

  useInterval(() => {
    // Your custom logic here
    setCount(count + 1);
  }, 1000);

  const resetInterval = () => {};

  return (
    <>
      <h1>{count}</h1>
      <button ocClick={resetInterval}>Reset</button>
    </>
  );
}

4 个答案:

答案 0 :(得分:1)

要重置计数器,请从setCount(0)调用resetInterval

注意:您在该按钮上拼错了onClick

function Counter() {
  const [count, setCount] = useState(0);

  useInterval(() => {
    // Your custom logic here
    setCount(count => count + 1);
  }, 1000);

  const resetInterval = () => setCount(0);

  return (
    <>
      <h1>{count}</h1>
      <button onClick={resetInterval}>Reset</button>
    </>
  );
}

要停止/恢复间隔,您可以重构useInterval以返回toggleRunning函数和当前running状态。

function useInterval(callback, delay) {
  const savedCallback = useRef();
  const intervalId = useRef(null);
  const [currentDelay, setDelay] = useState(delay);

  const toggleRunning = useCallback(
    () => setDelay(currentDelay => (currentDelay === null ? delay : null)),
    [delay]
  );

  const clear = useCallback(() => clearInterval(intervalId.current), []);

  // Remember the latest function.
  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  // Set up the interval.
  useEffect(() => {
    function tick() {
      savedCallback.current();
    }

    if (intervalId.current) clear();

    if (currentDelay !== null) {
      intervalId.current = setInterval(tick, currentDelay);
    }

    return clear;
  }, [currentDelay, clear]);

  return [toggleRunning, !!currentDelay];
}

带有重置和暂停/恢复(Sandbox)的工作示例

const { useState, useEffect, useRef, useCallback, Fragment } = React;

function Counter() {
  const [count, setCount] = useState(0);

  const [toggle, running] = useInterval(() => {
    // Your custom logic here
    setCount(count => count + 1);
  }, 100);

  const resetCounter = () => setCount(0);

  return (
    <Fragment>
      <h1>{count}</h1>
      <button onClick={resetCounter}>Reset</button>
      <button onClick={toggle}>{running ? "Pause" : "Resume"}</button>
    </Fragment>
  );
}

function useInterval(callback, delay) {
  const savedCallback = useRef();
  const intervalId = useRef(null);
  const [currentDelay, setDelay] = useState(delay);

  const toggleRunning = useCallback(
    () => setDelay(currentDelay => (currentDelay === null ? delay : null)),
    [delay]
  );

  const clear = useCallback(() => clearInterval(intervalId.current), []);

  // Remember the latest function.
  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  // Set up the interval.
  useEffect(() => {
    function tick() {
      savedCallback.current();
    }

    if (intervalId.current) clear();

    if (currentDelay !== null) {
      intervalId.current = setInterval(tick, currentDelay);
    }

    return clear;
  }, [currentDelay, clear]);

  return [toggleRunning, !!currentDelay];
}

ReactDOM.render(<Counter />, root);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>

答案 1 :(得分:1)

如果要clearInterval并停止/重置计数器,请查看下一个示例:

function Counter() {
  const [count, setCount] = useState(0);

  const intervalId = useRef();

  useEffect(() => {
    intervalId.current = setInterval(() => {
      setCount(prev => prev + 1);
    }, 1000);
    return () => clearInterval(intervalId.current);
  }, []);

  return (
    <>
      <h1>{count}</h1>
      <button
        onClick={() => {
          setCount(0);
        }}
      >
        Reset Counter and Continue Counting
      </button>
      <button
        onClick={() => {
          setCount(0);
          clearInterval(intervalId.current);
        }}
      >
        Reset and Stop Count
      </button>
      <button
        onClick={() => {
          clearInterval(intervalId.current);
        }}
      >
        Stop Count and Clear Interval
      </button>
    </>
  );
}

Edit Q-56952038-ClearIntervalOnClick

答案 2 :(得分:0)

只需将状态设置为0

 const resetInterval = () => {setCount(0)};

  return (
    <div>
      <h1>{count}</h1>
      <button onClick={resetInterval}>Reset</button>
    </div>
  );

您似乎错误地输入了onClick,这就是为什么它无法正常工作

答案 3 :(得分:0)

据我所知,您可以使用额外的reset状态,将其传递给useInterval,在每次重置更改时都以某种方式更改此状态(我只是在增加它),然后再使用在诸如callback之类的引用中声明,并比较useInterval中当前和旧版本。

import React from "react";
import ReactDOM from "react-dom";

function Counter() {
  const [count, setCount] = React.useState(0);
  const [delay, setDelay] = React.useState(1000);
  const [isRunning, setIsRunning] = React.useState(true);
  const [reset, setReset] = React.useState(0);

  useInterval(() => {
    // Your custom logic here
    setCount(count + 1);
  }, isRunning ? delay : null, reset);

  function handleDelayChange(e) {
    setDelay(Number(e.target.value));
  }

  function handleIsRunningChange(e) {
    setIsRunning(e.target.checked);
  }

  function handleResetChange() {
    setReset(c => c + 1);
    setCount(0);
  }

  return (
    <>
      <h1>{count}</h1>
      <input type="checkbox" checked={isRunning} onChange={handleIsRunningChange} /> Running
      <br />
      <input value={delay} onChange={handleDelayChange} />
      <button onClick={handleResetChange}>Reset</button>
    </>
  );
}

function useInterval(callback, delay, reset) {
  const savedCallback = React.useRef();
  const savedReset = React.useRef();
  // Remember the latest function.
  React.useEffect(() => {
    savedCallback.current = callback;
    savedReset.current = reset;
  }, [callback, reset]);

  // Set up the interval.
  React.useEffect(() => {
    function tick() {
      savedCallback.current();
    }
    if (delay !== null || reset !== savedReset.current) {
      let id = setInterval(tick, delay);
      return () => {console.log("cleared", id); clearInterval(id)};
    }
  }, [delay, reset]);
}

const rootElement = document.getElementById("root");
ReactDOM.render(<Counter />, rootElement);

CodeSandbox example