我如何使用 React Hooks 在单击时清除间隔? [英] how do I clearInterval on-click, with React Hooks?

查看:93
本文介绍了我如何使用 React Hooks 在单击时清除间隔?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

谢谢,

useTimeout

import { useState, useEffect } from 'react';让计时器=空;const useTimeout = () =>{const [count, setCount] = useState(0);const [timerOn, setTimerOn] = useState(false);useEffect(() => {如果(定时器){console.log("timerOn ", timerOn);计时器 = setInterval(() => {setCount((prev) => prev + 1)}, 1000);} 别的 {console.log("timerOn ", timerOn);清除间隔(定时器);设置计数(0);}返回 () =>{清除间隔(定时器);}}, [打开定时器])返回 [count, setCount, setTimerOn];}导出默认使用超时;

组件

从'react'导入React;从 './useTimeout' 导入 useTimeout;const UseStateExample = () =>{const [count, setCount, setTimerOn] = useTimeout()返回 (<div><h2>注意事项:</h2><p>在每次渲染时创建新函数</p><br/><h2>count = {count}</h2><button onClick={() =>setCount(prev => prev + 1)}>Increment<br/><button onClick={() =>setCount(prev => prev - 1)}>Decrement<br/><button onClick={() =>setTimerOn(true)}>设置间隔</button><br/><button onClick={() =>setTimerOn(false)}>停止间隔</button><br/>

);}导出默认的 UseStateExample;

解决方案

--- added @ 2019-02-11 15:58 ---

在 Hooks API 中使用 setInterval 的好模式:

https://overreacted.io/making-setinterval-declarative-with-反应钩子/

<小时>

--- 原答案---

一些问题:

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

  2. 在else"分支中不需要清除定时器,因为如果timerOn从真变为假,则返回函数将被执行.

我认为更好的方法:

import { useState, useEffect } from 'react';导出默认值(处理程序,间隔)=>{const [intervalId, setIntervalId] = useState();useEffect(() => {const id = setInterval(handler, interval);setIntervalId(id);返回 () =>clearInterval(id);}, []);返回 () =>clearInterval(intervalId);};

在此处运行示例:

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

I'm trying to refactor my code to react hooks, but I'm not sure if i'm doing it correctly. I tried copying and pasting my setInterval/setTimout code into hooks, but it did not work as intended. After trying different things I was able to get it to work, but I'm not sure if this is the best way to do it.

I know i can use useEffect to clear interval on un-mount, but I want to clear it before un-mounting.

Is the following good practice and if not what is a better way of clearing setInterval/setTimout before un-mounting?

Thanks,

useTimeout

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;

Component

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;

解决方案

--- added @ 2019-02-11 15:58 ---

A good pattern to use setInterval with Hooks API:

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


--- origin answer ---

Some issues:

  1. Do not use non-constant variables in the global scope of any modules. If you use two instances of this module in one page, they’ll share those global variables.

  2. There’s no need to clear timer in the "else" branch because if the timerOn change from true to false, the return function will be executed.

A better way in my thoughts:

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

Running example here:

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

这篇关于我如何使用 React Hooks 在单击时清除间隔?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆