[英]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.