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

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

博文 《"How React Uses Closures to Avoid Bugs"》(epicreact.dev/how-react-u…) 解释了当 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 依赖项,可能会遇到一些严重的错误,因此请不要忽略 www.npmjs.com/package/esl… 规则。

结论

在到处使用“最新 Ref 模式”之前,我建议您充分了解您正在规避的内容,因此,如果还没有这样做,请仔细阅读 《React 如何使用闭包避免错误》(epicreact.dev/how-react-u…



相关文章
|
7月前
|
前端开发 JavaScript API
第八章 react组件实例中三大属性之ref
第八章 react组件实例中三大属性之ref
|
3月前
|
前端开发 JavaScript
学习react基础(3)_setState、state、jsx、使用ref的几种形式
本文探讨了React中this.setState和this.state的区别,以及React的核心概念,包括核心库的使用、JSX语法、类与函数组件的区别、事件处理和ref的使用。
83 3
学习react基础(3)_setState、state、jsx、使用ref的几种形式
|
3月前
|
JavaScript 前端开发 开发者
React 的正确使用方法:ref 篇
你真的用对了 useRef 吗?在与 TypeScript 一起使用、以及撰写组件库的情况下,你的写法能够避开以下所有场景的坑吗?
|
4月前
|
移动开发 资源调度 前端开发
介绍React路由模式
【8月更文挑战第10天】介绍React路由模式
63 12
|
4月前
|
JavaScript 前端开发 API
[译] 用 Vue 3 Composition API 实现 React Context/Provider 模式
[译] 用 Vue 3 Composition API 实现 React Context/Provider 模式
|
3月前
|
前端开发
react学习(17)回调形式的ref
react学习(17)回调形式的ref
|
3月前
|
存储 前端开发 容器
react学习(18)createRef形式的ref
react学习(18)createRef形式的ref
|
3月前
|
移动开发 前端开发 应用服务中间件
React两种路由模式的实现原理
React两种路由模式的实现原理
103 3
|
4月前
|
前端开发 人机交互
langchain 入门指南 - ReAct 模式
langchain 入门指南 - ReAct 模式
114 1
|
5月前
|
JavaScript
react18【系列实用教程】useRef —— 创建 ref 对象,获取 DOM (2024最新版)
react18【系列实用教程】useRef —— 创建 ref 对象,获取 DOM (2024最新版)
63 0