如何使用反应挂钩重置 setInterval 函数

How to reset setInterval function using react hooks

我正在使用 useInterval 钩子,作者 Dan Abramov 来自 here

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

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>
    </>
  );
}

要重置计数器,请从 resetInterval:

调用 setCount(0)

注意: 你在按钮上拼错了 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>
    </>
  );
}

到stop/resume你可以重构useInterval到return一个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];
}

使用 Reset 和 Pause/Resume (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>

只需将状态设置为0

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

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

您似乎输入了错误的 onClick,这就是它不起作用的原因

如果您想 clearInterval 和 stop/reset 计数器,请查看下一个示例:

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>
    </>
  );
}

据我所知,您可以使用额外的 reset 状态,将其传递给 useInterval,在每次重置更改时以某种方式更改此状态(我只是增加它),然后在 callback 之类的 ref 中使用此状态,并在 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