什么时候使用无依赖vs.直接分配的useEffect? [英] When to use useEffect without dependencies vs. direct assignment?
问题描述
我正在编写一个React挂钩,允许我在组件中使用 setInterval
.为此,我需要将最新版本的回调保留在ref中,以便以后可以从时间间隔的范围进行访问.
I am writing a React hook that allows me to use setInterval
in my components. In order to do so I need to keep the latest version of the callback in a ref so that it can be accessed from the scope of the interval later on.
到目前为止,这是我的代码:
This is my code so far:
import { useRef, useEffect } from 'react'
export default function useInterval(
callback: () => void,
delay: number | null,
) {
const callbackRef = useRef(callback)
// Remember the latest callback.
useEffect(() => {
callbackRef.current = callback
})
useEffect(() => {
// Don't schedule if no delay is specified.
if (delay === null) {
return
}
const id = setInterval(() => callbackRef.current(), delay)
return () => clearInterval(id)
}, [delay])
}
我的问题是有关 useEffect
的第一个实例,其中将最新值传递给引用.根据React文档,此代码将在我的组件渲染后执行.
My question is about the first instance of useEffect
where the latest value is passed to the ref. According the the React documentation this code will execute after my component has rendered.
我可以想象当将ref传递给元素时,这很有用,因此可以确保在呈现之后它具有一个值.但是,如果我的代码不关心组件何时呈现,将其保留在 useEffect
中是否仍然有意义?
I can imagine this is useful when you are passing a ref to an element so you can be sure that it has a value after it has rendered. But if my code doesn't care about when the component renders, does it still make sense to keep this in a useEffect
?
按如下方式重写代码是否有意义:
Would it make sense that I rewrite the code as follows:
import { useRef, useEffect } from 'react'
export default function useInterval(
callback: () => void,
delay: number | null,
) {
const callbackRef = useRef(callback)
// Remember the latest callback.
callbackRef.current = callback
useEffect(() => {
// Don't schedule if no delay is specified.
if (delay === null) {
return
}
const id = setInterval(() => callbackRef.current(), delay)
return () => clearInterval(id)
}, [delay])
}
推荐答案
何时在没有依赖与直接分配的情况下使用 useEffect
?
来自文档:
When to use useEffect
without dependencies vs. direct assignment?
From docs:
效果挂钩可让您在功能组件中执行副作用
The Effect Hook lets you perform side effects in function components
- 没有依赖项的
useEffect
(或未定义为undefined
的依赖项)将在第一次渲染时运行,并每次重新渲染,但是总是有副作用,即在组件已渲染后 . - 直接分配(同步操作)将在首次渲染时运行,并每随后重新渲染,但始终与渲染周期相同.它可能会影响性能或延迟渲染.
- A
useEffect
without dependencies (orundefined
as dependencies) will be run at first render and every subsequent re-render, But always as a side-effect i.e. after the component has rendered. - A direct assignment (a sync operation) will be run at first render and every subsequent re-render, But always as in the render cycle. It may affect performance or delay the rendering.
那么,什么时候使用哪个?这取决于您的用例.
So, when to use which one? It depends on your use case.
我会说都不是
useEffect(() => {
callbackRef.current = callback
})
也
callbackRef.current = callback
在这种情况下似乎是正确的.
seems correct in this use case.
因为我们不想在每次重新渲染时进行分配- callbackRef.current = callback
.但是,当 callback
发生变化时,我们希望这样做.因此,以下选项似乎更好:
Because we don't want to do the assignment - callbackRef.current = callback
at every re-render. But we want to do it when there is a change in callback
. So, the below one seems better:
useEffect(() => {
callbackRef.current = callback
}, [callback])
您可能会看到此博客和一个演示,显示一个效果作为副作用运行(记录在效果内部始终是最后一个):
A demo which shows that an effect runs after as a side-effect (Log inside effect is always the last):
function useInterval(callback, delay) {
const callbackRef = React.useRef(callback)
React.useEffect(() => {
callbackRef.current = callback
}, [callback])
React.useEffect(() => {
if (delay !== null) {
const id = setInterval(() => callbackRef.current(), delay)
return () => clearInterval(id)
}
}, [delay])
}
function Demo() {
const [count, setCount] = React.useState(0)
function doThis() {
setCount(count + 1)
}
useInterval(doThis, 1000)
console.log('log - before effect')
React.useEffect(() => {
console.log('log inside effect')
})
console.log('log - after effect')
return <h1>{count}</h1>
}
ReactDOM.render(<Demo />, document.getElementById('root'))
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<body>
<div id="root"></div>
</body>
这篇关于什么时候使用无依赖vs.直接分配的useEffect?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!