小编典典

React hooks - 清除超时和间隔的正确方法

all

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

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
}

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

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

阅读 73

收藏
2022-07-27

共1个答案

小编典典

每次运行时都运行return () => { /*code/* }内部定义的函数(组件安装时的第一次渲染除外)和组件卸载时(如果您不再显示组件)。useEffect``useEffect

这是一种使用和清除超时或间隔的工作方式:

沙盒示例

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

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

沙盒示例。

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

丹·阿布拉莫夫的文章

2022-07-27