Как сбросить функцию setInterval с помощью ответных хуков - PullRequest
0 голосов
/ 09 июля 2019

Я использую useInterval хук, написанный Даном Абрамовым из здесь

Как мне сбросить счетчик?Например, нажмите на кнопку?

Код на коды и поле

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 ]

1 голос
/ 09 июля 2019

Если вы хотите 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

1 голос
/ 09 июля 2019

Чтобы сбросить счетчик, позвоните 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];
}

Пример работы с перезагрузкой и паузой / возобновлением ( Песочница *)1018 *)

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 голосов
/ 09 июля 2019

Насколько я вижу, вы можете использовать дополнительное состояние 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

0 голосов
/ 09 июля 2019

Просто установите состояние на 0

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

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

Похоже, что вы ошиблись при клике, и поэтому он не работал

...