[译] React 中的 "最新 Ref 模式"

文章介绍了ReactHooks中的最新Ref模式,用于在不触发重新渲染的情况下跟踪callback,避免使用useState可能引发的无限循环。通过useRef和useLayoutEffect,确保总是调用到callback的最新版本。同时强调不应将ref.current包含在依赖数组中,遵循exhaustive-deps规则,但需谨慎处理非ref依赖项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

c9fde982c25f2113614cabd85ecc6c36.png

原文: https://epicreact.dev/the-latest-ref-pattern-in-react/

博文 《"How React Uses Closures to Avoid Bugs"》(https://epicreact.dev/how-react-uses-closures-to-avoid-bugs) 解释了当 React 从类和生命周期转换到函数和 hooks 时所做的一些权衡;我想在这个主题上深入一下。

在那篇文章中,有以下示例:

function useDebounce(callback, delay) {
  const callbackRef = React.useRef(callback)
  React.useLayoutEffect(() => {
    callbackRef.current = callback
  })
  return React.useMemo(
    () => debounce((...args) => callbackRef.current(...args), delay),
    [delay],
  )
}

hook 的创始人 Yago 喜欢称之为“最新Ref模式”的模式。

这个模式本身非常简单。这就是模式的部分:

const callbackRef = React.useRef(callback)
React.useLayoutEffect(() => {
  callbackRef.current = callback
})

就是这样而已。

那么为什么要这样做呢?好吧,让我们考虑何时使用 useRef。当你想跟踪一个值但不想在更新它时触发重新渲染时,就可以使用useRef。所以在例子中,我们正试图跟踪callback。这样做的原因是,我们希望始终调用最新版本的callback,而不是旧渲染中的版本。

但是为什么不使用useState呢?是否可以在实际的状态值中跟踪这个最新的回调值?我们不想使用useState,因为当更新到最新值时,不需要触发组件重新渲染。实际上,在我们的例子中,如果尝试这样做,将触发一个无限循环(试试看吧😈)。

由于不需要也不希望在将callback更新为最新值时重新渲染组件,这意味着我们也不需要(而且实际上不应该)将它包含在useEffectuseCallback或例子的useMemo依赖数组中。这是一个重要的观点,因此我想深入探讨一下。

遵循eslint-plugin-react-hooks/exhaustive-deps规则并始终包括所有依赖项非常重要。但是您应该跳过引用的“current”值。所以永远不要这样做:

// ❌ 永远不要这样做
React.useEffect(() => {}, [ref.current])

这是因为更新引用不会触发重新渲染,所以 React 无法在更新引用时调用 effect 回调函数或更新记忆化值。因此,如果将 ref.current 包含在依赖项数组中,你将触发怪异且难以调试的行为。顺便说一下,由于 ref 本身是一个稳定的对象,因此是否在依赖项数组中包含 ref 对象本身并不重要:

// 🤷‍♂️ 是否包含 ref 都没关系
React.useEffect(() => {}, [ref])

但是,如果没有包含所有非 ref 依赖项,可能会遇到一些严重的错误,因此请不要忽略 https://www.npmjs.com/package/eslint-plugin-react-hooks 规则。

结论

在到处使用“最新 Ref 模式”之前,我建议您充分了解您正在规避的内容,因此,如果还没有这样做,请仔细阅读 《React 如何使用闭包避免错误》(https://epicreact.dev/how-react-uses-closures-to-avoid-bugs)。这将帮助您更好地了解何时可以使用此特定模式。

注意身体,保重 👍

9ddc00d6ce04d869fc8762b595ed0e81.png2211e1875768484c1e41c5612bd23df7.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值