javascript - 如何使用 react 钩子(Hook)重置 setInterval 函数

标签 javascript reactjs react-hooks

我正在使用 useInterval 钩子(Hook),由 here 中的 Dan Abramov 编写

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

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

要停止/恢复间隔,您可以重构 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>

关于javascript - 如何使用 react 钩子(Hook)重置 setInterval 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56952038/

相关文章:

reactjs - expect(received).toEqual(expected) - 错误

reactjs - 使用 React 显示隐藏多个元素

reactjs - 如何防止扩展的 React-Table 行在重新渲染时折叠?

javascript - 如何通过 api 使用 react 选择

reactjs - React hooks useEffect() 清理仅用于 componentWillUnmount?

javascript - 根据内部元素过滤掉整个div

javascript - 如何将 onclick 函数更改为具有多个函数?

javascript - 获取复选框选定的值

javascript - 是否需要 Redux 在左侧显示 ItemList,在右侧显示 ItemContent?

javascript - 如何从数组构建正则表达式或选项