簡體   English   中英

為什么如果我在自定義反應鈎子中使用 setTimeout,我是否必須將它包裝在 useEffect 中?

[英]Why is if I use setTimeout inside a custom react hook, do i have to wrap it in a with useEffect?

為什么需要將此自定義鈎子的 settimeout 包裝在 useEffect 鈎子中?

function useWait (delay) {
  const [show, setShow] = React.useState(false)

  React.useEffect(() => {
    const id = window.setTimeout(() => {
      setShow(true)
    }, delay)

    return () => window.clearTimeout(id)
  }, [delay])

  return show
}

如果您沒有在 useEffect 中放置 setTimeout 或 setInterval,則每次您的組件重新渲染時,它都會被重新初始化並且不會被清除。

看下面的例子。 每次按下按鈕增加計數器時,父組件都會重新渲染,這會逐漸重新渲染到所有子組件(包括我的 setTimeout 組件)。 按幾次按鈕,你會看到組件重新渲染了幾次,然后你會看到幾次“超時完成”。

然后在下面我添加了一個帶有 useEffect 的片段,您將看到超時僅運行一次。

這回答了你的問題了嗎?

編輯:這是一個 codesandbox 來試用它們https://codesandbox.io/s/boring-liskov-4kjgm?fontsize=14&hidenavigation=1&theme=dark

沒有使用效果

import React, {useState} from "react";
import ReactDOM from "react-dom";

import "./styles.css";

function App() {
  const [counter, increment] = useState(0);
  const doIncrement = () => increment(counter + 1);
  return (
    <div className="App">
      <Counter counter={counter} increment={doIncrement} />
      <OtherComponent />
    </div>
  );
}

const Counter = ({counter, increment}) => {
  return <button onClick={()=>increment()}>{counter}</button>
}

const OtherComponent = () => {
  console.log('I rerendered');
  const timeout = setTimeout(() => console.log('timeout finished'), 1000)
  return <h1> Hello world </h1>
}



const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

使用效果

import React, {useState, useEffect} from "react";
import ReactDOM from "react-dom";

import "./styles.css";

function App() {
  const [counter, increment] = useState(0);
  const doIncrement = () => increment(counter + 1);
  return (
    <div className="App">
      <Counter counter={counter} increment={doIncrement} />
      <OtherComponent />
    </div>
  );
}

const Counter = ({counter, increment}) => {
  return <button onClick={()=>increment()}>{counter}</button>
}

const OtherComponent = () => {
  console.log('I rerendered');
  useEffect(() => {
     const timeout = setTimeout(() => console.log('timeout finished'), 1000)
     return () => clearTimeout(timeout)
  }, [])

  return <h1> Hello world </h1>
}



const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM