我如何使用 React Hooks 在单击时清除间隔?

Ar-*_*-51 7 reactjs react-hooks

我正在尝试重构我的代码以响应钩子,但我不确定我是否正确执行。我尝试将我的 setInterval/setTimout 代码复制并粘贴到钩子中,但它没有按预期工作。在尝试了不同的事情后,我能够让它工作,但我不确定这是否是最好的方法。

我知道我可以使用 useEffect 在卸载时清除间隔,但我想在卸载前清除它。

以下是良好的做法,如果不是,在卸载之前清除 setInterval/setTimout 的更好方法是什么?

谢谢,

使用超时

import { useState, useEffect } from 'react';

let timer = null;

const useTimeout = () => {
    const [count, setCount] = useState(0);
    const [timerOn, setTimerOn] = useState(false);

    useEffect(() => {
        if (timerOn) {
            console.log("timerOn ", timerOn);

            timer = setInterval(() => {
                setCount((prev) => prev + 1)
            }, 1000);

        } else {
            console.log("timerOn ", timerOn);
            clearInterval(timer);
            setCount(0);
        }
    return () => {
        clearInterval(timer);
    }
    }, [timerOn])

    return [count, setCount, setTimerOn];
}

export default useTimeout;
Run Code Online (Sandbox Code Playgroud)

成分

import React from 'react';
import useTimeout from './useTimeout';

const UseStateExample = () => {
    const [count, setCount, setTimerOn] = useTimeout()
    return (
        <div>
            <h2>Notes:</h2>
            <p>New function are created on each render</p>
            <br />
            <h2>count = {count}</h2>
            <button onClick={() => setCount(prev => prev + 1)}>Increment</button>
            <br />
            <button onClick={() => setCount(prev => prev - 1)}>Decrement</button>
            <br />
            <button onClick={() => setTimerOn(true)}>Set Interval</button>
            <br />
            <button onClick={() => setTimerOn(false)}>Stop Interval</button>
            <br />

        </div>
    );
}

export default UseStateExample;
Run Code Online (Sandbox Code Playgroud)

李元秋*_*李元秋 15

--- 添加@ 2019-02-11 15:58 ---

setInterval与 Hooks API一起使用的好模式:

https://overreacted.io/making-setinterval-declarative-with-react-hooks/


--- 原答案---

一些问题:

  1. 不要在任何模块的全局范围内使用非常量变量。如果您在一页中使用此模块的两个实例,它们将共享这些全局变量。

  2. 在“else”分支中不需要清除计时器,因为如果timerOn从真变为假,将执行返回函数。

我认为更好的方法:

import { useState, useEffect } from 'react';

export default (handler, interval) => {
  const [intervalId, setIntervalId] = useState();
  useEffect(() => {
    const id = setInterval(handler, interval);
    setIntervalId(id);
    return () => clearInterval(id);
  }, []);
  return () => clearInterval(intervalId);
};
Run Code Online (Sandbox Code Playgroud)

在这里运行示例:

https://codesandbox.io/embed/52o442wq8l?codemirror=1

  • @skyboyer 我同意你的看法。我们可以看到将 setInterval 与 Hooks API 一起使用的“官方方式”:https://overreacted.io/making-setinterval-declarative-with-react-hooks/ (2认同)