[英]When to use useEffect without dependencies vs. direct assignment?
我正在编写一个允许我在组件中使用setInterval
的 React 钩子。 为此,我需要将最新版本的回调保存在 ref 中,以便稍后可以从间隔的 scope 访问它。
到目前为止,这是我的代码:
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
的第一个实例,其中最新值被传递给 ref。 根据 React 文档,此代码将在我的组件渲染后执行。
我可以想象这在您将 ref 传递给元素时很有用,因此您可以确定它在渲染后具有值。 但是,如果我的代码不关心组件何时呈现,那么将其保留在useEffect
中是否仍然有意义?
我将代码重写如下是否有意义:
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
与直接分配?来自文档:
Effect Hook 允许您在 function 组件中执行副作用
undefined
为依赖项)的useEffect
将在第一次渲染和每次后续重新渲染时运行,但始终作为副作用,即在组件渲染之后。那么,什么时候用哪一个呢? 这取决于您的用例。
我不会说
useEffect(() => {
callbackRef.current = callback
})
也不
callbackRef.current = callback
在这个用例中似乎是正确的。
因为我们不想在每次重新渲染时进行分配 - callbackRef.current = callback
。 但是我们想在callback
发生变化时这样做。 所以,下面的似乎更好:
useEffect(() => {
callbackRef.current = callback
}, [callback])
显示效果作为副作用运行的演示(日志内部效果始终是最后一个):
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>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.