使用 createRef 创建的 ref 在每次渲染时不应该是相同的吗?

Posted

技术标签:

【中文标题】使用 createRef 创建的 ref 在每次渲染时不应该是相同的吗?【英文标题】:Isn't the ref created with createRef supposed to be the same at each render? 【发布时间】:2020-11-27 06:12:05 【问题描述】:

我不了解 ref 系统在 React 钩子中的基本行为。

我知道 useRef 会创建一个常量对象,每次渲染期间只有当前属性会改变。

我希望 createRef 表现相同,但显然不是:

这段代码正在创建一个无限循环

import React from "react";

export default function App() 
  const [count, setCount] = React.useState(0)
  const ref = React.createRef()
  React.useLayoutEffect(() => setCount(count => count+1), [ref])
  return (
    <h1 ref=ref>count</h1>
  );

这段代码不是:

import React from "react";

export default function App() 
  const [count, setCount] = React.useState(0)
  const ref = React.useRef()
  React.useLayoutEffect(() => setCount(count => count+1), [ref])
  return (
    <h1 ref=ref>count</h1>
  );

那么,createRef 背后的魔力是什么?

此外,我遇到了一些暗示测量儿童的案例,这种行为确实存在问题。那么使用 createRef 而不是 useRef 有什么意义呢?

【问题讨论】:

简而言之,createRef 用于类组件,useRef 用于函数。 我会将此帖子设置为与此 one 重复 这能回答你的问题吗? What's the difference between `useRef` and `createRef`? 实际上,我发现@RobinZigmond 的答案对我的问题更准确。但是您可以将其标记为重复。谢谢 【参考方案1】:

createRef 总是会在每次渲染组件时创建一个新的 ref。因此,您会看到 createRef 在类组件的构造函数中被初始化,或者 useRef 返回一个可变对象,该对象根据官方文档的描述在组件的生命周期内持续存在:

useRef 返回一个可变的 ref 对象,其 .current 属性为 初始化为传递的参数(initialValue)。返回的对象 将在组件的整个生命周期内持续存在。

我对此的理解是,使用钩子实现功能组件,每个渲染都有自己的闭包,因此使用useRef,我们将其变异为在每个渲染上都相同。而在类组件中,构造函数只被调用一次,因此您只需完成一次初始化。

【讨论】:

据我了解,createRef 用于类,useRef 用于功能。但这不是应该在文档中以更清晰的方式显示吗? >reactjs.org/docs/refs-and-the-dom.html#creating-refs @Sharcoux 那些文档只讨论类组件——它们肯定早于 Hooks。这是一个有趣的问题,为什么它们没有被更新或编写并行的,以使用带有 Hooks 的功能组件。但就像现在一样,Hooks 是单独记录的,useRef 被描述为here。我同意,如果能清楚地解释它与createRef 的不同之处,那就太好了——但两组文档的上下文仍然明显不同。一种是使用类组件,另一种是使用钩子的功能组件。 我链接的页面在某些部分提到了功能组件。我做了一个 PR 来更新文档。我们将看看它是否至少会引发讨论以刷新文档。直到现在我都坚信 createRef 是在函数中创建 ref 的方法。

以上是关于使用 createRef 创建的 ref 在每次渲染时不应该是相同的吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 React createRef

React.JS Ref 中的 Ref 错误 - createRef、useRef 和 using Refs

使用 useRef 或 createRef 而不是 inline ref 有啥优势?

createRef和useRef区别——useRef的使用——forwardRef完成类组件的绑定—— useImperativeHandle——映射ref对象——更新同步

createRef和useRef区别——useRef的使用——forwardRef完成类组件的绑定—— useImperativeHandle——映射ref对象——更新同步

[react ] TextArea 光标定位到最后