React hooks - 清除超时和间隔的正确方法 [英] React hooks - right way to clear timeouts and intervals

查看:79
本文介绍了React hooks - 清除超时和间隔的正确方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不明白为什么当我使用 setTimeout 函数时,我的反应组件开始无限的 console.log.一切正常,但 PC 开始滞后.有人说超时功能会改变我的状态和重新渲染组件,设置新的计时器等等.现在我需要了解如何清除它是正确的.

导出默认函数 Loading() {//如果数据获取很慢,1 秒后我会显示一些加载动画const [showLoading, setShowLoading] = useState(true)让 timer1 = setTimeout(() => setShowLoading(true), 1000)console.log('此消息将每秒渲染一次')返回 1}

清除不同版本的代码无济于事:

const [showLoading, setShowLoading] = useState(true)让 timer1 = setTimeout(() => setShowLoading(true), 1000)使用效果(() =>{返回 () =>{清除超时(定时器 1)}},[showLoading])

解决方案

Defined return () =>{/*code/* } 内部 useEffect 函数在每次 useEffect 运行时运行(除了第一次在组件挂载时渲染)和在组件卸载时(如果你不这样做)t 不再显示组件).

这是一种使用和清除超时或间隔的有效方法:

沙盒示例.

import { useState, useEffect } from react";常量延迟 = 5;导出默认函数 App() {const [show, setShow] = useState(false);使用效果(() =>{让 timer1 = setTimeout(() => setShow(true), delay * 1000);//这将清除超时//当像 willComponentUnmount 那样卸载组件时//并且显示不会变为真返回 () =>{清除超时(定时器 1);};},//useEffect 只会在空 [] 时运行一次//如果你将一个值传递给数组,//像这样 - [数据]//比 clearTimeout 每次都会运行//这个值改变了(useEffect重新运行)[]);回归表演?(<div>show 为真,{延迟}秒过去了</div>) : (<div>show 是假的,等待 {delay} 秒</div>);}

如果您需要清除另一个组件中的超时或间隔:

沙盒示例.

import { useState, useEffect, useRef } from react";常量延迟 = 1;导出默认函数 App() {const [计数器,setCounter] = useState(0);const timer = useRef(null);//我们可以将计时器保存在 useRef 中并将其传递给 childuseEffect(() => {//useRef 值存储在 .current 属性中timer.current = setInterval(() => setCounter((v) => v + 1), delay * 1000);//在组件卸载时清除返回 () =>{clearInterval(timer.current);};}, []);返回 (<div><div>间隔有效,计数器为:{counter}</div><子计数器={counter} currentTimer={timer.current}/>

);}function Child({ counter, currentTimer }) {//这将在计数器达到 5 后清除父组件中的间隔useEffect(() => {如果(计数器<5)返回;clearInterval(currentTimer);}, [计数器, 当前定时器]);返回空;}

来自 Dan Abramov 的文章.

I don't understand why is when I use setTimeout function my react component start to infinite console.log. Everything is working, but PC start to lag as hell. Some people saying that function in timeout changing my state and that rerender component, that sets new timer and so on. Now I need to understand how to clear it's right.

export default function Loading() {
  // if data fetching is slow, after 1 sec i will show some loading animation
  const [showLoading, setShowLoading] = useState(true)
  let timer1 = setTimeout(() => setShowLoading(true), 1000)

  console.log('this message will render  every second')
  return 1
}

Clear in different version of code not helping to:

const [showLoading, setShowLoading] = useState(true)
  let timer1 = setTimeout(() => setShowLoading(true), 1000)
  useEffect(
    () => {
      return () => {
        clearTimeout(timer1)
      }
    },
    [showLoading]
  )

解决方案

Defined return () => { /*code/* } function inside useEffect runs every time useEffect runs (except first render on component mount) and on component unmount (if you don't display component any more).

This is a working way to use and clear timeouts or intervals:

Sandbox example.

import { useState, useEffect } from "react";

const delay = 5;

export default function App() {
  const [show, setShow] = useState(false);

  useEffect(
    () => {
      let timer1 = setTimeout(() => setShow(true), delay * 1000);

      // this will clear Timeout
      // when component unmount like in willComponentUnmount
      // and show will not change to true
      return () => {
        clearTimeout(timer1);
      };
    },
    // useEffect will run only one time with empty []
    // if you pass a value to array,
    // like this - [data]
    // than clearTimeout will run every time
    // this value changes (useEffect re-run)
    []
  );

  return show ? (
    <div>show is true, {delay}seconds passed</div>
  ) : (
    <div>show is false, wait {delay}seconds</div>
  );
}

If you need to clear timeouts or intervals in another component:

Sandbox example.

import { useState, useEffect, useRef } from "react";

const delay = 1;

export default function App() {
  const [counter, setCounter] = useState(0);
  const timer = useRef(null); // we can save timer in useRef and pass it to child

  useEffect(() => {
    // useRef value stored in .current property
    timer.current = setInterval(() => setCounter((v) => v + 1), delay * 1000);

    // clear on component unmount
    return () => {
      clearInterval(timer.current);
    };
  }, []);

  return (
    <div>
      <div>Interval is working, counter is: {counter}</div>
      <Child counter={counter} currentTimer={timer.current} />
    </div>
  );
}

function Child({ counter, currentTimer }) {
  // this will clearInterval in parent component after counter gets to 5
  useEffect(() => {
    if (counter < 5) return;

    clearInterval(currentTimer);
  }, [counter, currentTimer]);

  return null;
}

Article from Dan Abramov.

这篇关于React hooks - 清除超时和间隔的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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