揭秘 React Hooks:useRef

2025-05-27

揭秘 React Hooks:useRef

React Hooks 一经推出就改变了游戏规则!它们能够更简单地将状态行为和副作用封装在用户界面中,同时减少代码量并提升可读性。有些 Hooks 比其他 Hooks 更容易理解和使用,因此本系列文章将重点介绍那些不那么简单的 Hooks。

上周,我们深入探讨了 useCallback 和 useMemo。今天,我们先来解释一下命令式修改子元素和 DOM 的含义,然后重点介绍useRef 钩子的定义,并讨论如何使用、何时以及在何处使用它。

命令式地修改子元素和 DOM

如果你之前使用过 React,你一定熟悉父组件如何使用 props 与其子组件进行交互。为了使用不同的数据重新渲染子组件,父组件会传递新的 props。

有时,我们会遇到需要在典型的“传递 props”数据流之外强制修改子组件的情况,或者我们想要手动访问在 render 方法中创建的 DOM 节点或 React 元素。这时useRef()就派上用场了!

替代文本

为什么 useRef() Hook 很特殊?

useRef ()钩子在组件渲染之间持续存在(如状态)。

useRef 的神奇之处在于它可以发生变异而不会导致组件重新更新,因为 useRef 值存在于渲染周期之外。

如何使用 useRef() Hook?

您可以通过向useRef()钩子传递初始值或将其初始化为空并稍后更新其值来初始化它:

const testRef = useRef(1)

useRef()存储一个包含名为 的属性的对象current,该属性存储传递的值,在我们的示例中,它将保存值 1。

testRef = { current: 1 }

何时使用 useRef() Hook?

用于管理焦点、文本选择或媒体播放。文档中的大多数元素都具有 ref 属性,这方便使用 useRef 引用 HTML 中的元素。例如,看看这个<input/>HTML 标签,我们创建了一个 useRef 值并将其<input/>作为 ref 属性传递给它。现在,我们可以使用几个函数命令式地修改输入元素,使其获得<input/>焦点或模糊效果。

访问先前的值。useRef的另一个有用用途是存储状态的先前值。请看下面的示例,我们列出了三个宝可梦,你需要选择你最喜欢的。当前选中的是皮卡丘……但说实话,皮卡丘被高估了。选择任何其他选项,你都会在底部看到你之前的选择。这得益于我们 useRef hook 的使用:

const previousSelected = useRef()

然后,每次我们选择不同的选项时,我们都会在 changeSelection() 函数中跟踪先前的选择:

previousSelected.current = favPokemon

此外,根据 React Docs,refs 有助于触发命令式动画与第三方 DOM 库集成。

您应该在哪里更新 useRef() 值?

替代文本

更新 ref 值被视为副作用。这就是为什么你应该在事件处理程序和效果中更新 ref 值,而不是在渲染期间更新(除非你正在使用延迟初始化)。React 文档警告我们,不遵循此规则可能会导致意外行为。

你应该使用 refs 而不是 state 吗?

绝对不行。Refs 不是响应式的,这意味着改变它的值不会导致 HTML 更新。

看一下下面的例子,确保您理解为什么 refs 不应该取代 state。

我们初始化了一个状态和一个 ref,值为 1000 美元。这个组件允许你在每次点击按钮时一美元一美元地花费这些值Spend

当您花费状态中存储的金钱价值时,它会触发重新渲染并更新视图以向您显示新值。

现在,如果您花费 ref 中存储的金额,每次点击也会减去一美元,但是,这种变化不会触发重新渲染,因此您不会在 HTML 中看到变化。

您可以检查控制台以查看 ref 值在组件内部是否确实发生变化。

替代文本

useRef() 与 createRef 相同吗?

不。

createRef()可用于访问 DOM 节点或 React 元素。但是,在函数式组件中使用时,它会在每次渲染时创建一个新的 ref 实例,而不是在渲染之间保留一个值(如果你使用的是类组件,则不适用!)。

useRef()可用于访问 DOM 节点或 React 元素,并且即使组件重新渲染,它也能保留值。以下示例可以帮助您理解两者的区别。

看一下下面的代码,我们分别使用createRef和将两个 ref 值初始化为 null useRef

每次点击Add a render!按钮,我们都会更新renderCounter状态并触发重新渲染。每次渲染时,我们都会检查 refs 值是否为空,如果为空,则将当前renderCounter状态值赋给它。

请注意,使用 useRef 创建的 ref 值仅在第一次渲染时为空,因此它被设置为 1 一次,并且永远不会再被设置。

另一方面,使用 创建的 ref 值createRef是在每次渲染时创建的,因此它始终以 null 开始,然后重新分配下的当前状态值renderCounter

附注:这是一个简单的例子,用来说明 createRef 和 useRef 之间的区别。但是,修改 ref 的值应该在 effect 或事件处理程序中进行,而不是像本例中那样。

概括

useRef ()钩子有助于在功能组件内创建可变变量,该变量不会在每次渲染时更新。

  • Refs 有助于访问 DOM 节点或 React 元素(正在渲染的内容)以及在渲染之间保存值,例如状态的先前值。

  • useRef() 不应该用于替换状态,因为它不具有反应性并且不会触发重新渲染。

  • 应在效果和事件处理程序内部更新 Refs,以避免出现奇怪的行为。


我希望这篇文章能帮助您扩展对useRef()的理解,并希望您在未来的项目中开始利用此功能。

我每周都会发布新内容。下周末我们将探索一个不同的 React Hook!

在TwitterDev.to上关注我,了解最新帖子!

文章来源:https://dev.to/milu_franz/demystifying-react-hooks-useref-2ddp
PREV
Git 解释:基础知识
NEXT
在新西兰的货车上编写代码