繁体   English   中英

何时使用无依赖关系的 useEffect 与直接分配?

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM