前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[译] React 中的 "最新 Ref 模式"

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

作者头像
江米小枣
发布2023-12-06 16:23:30
1270
发布2023-12-06 16:23:30
举报
文章被收录于专栏:云前端云前端

原文: 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 时所做的一些权衡;我想在这个主题上深入一下。

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

代码语言:javascript
复制
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模式”的模式。

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

代码语言:javascript
复制
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”值。所以永远不要这样做:

代码语言:javascript
复制
// ❌ 永远不要这样做
React.useEffect(() => {}, [ref.current])

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

代码语言:javascript
复制
// 🤷‍♂️ 是否包含 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)。这将帮助您更好地了解何时可以使用此特定模式。

注意身体,保重 👍

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-03-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 云前端 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 结论
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档