使用 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.JS Ref 中的 Ref 错误 - createRef、useRef 和 using Refs
使用 useRef 或 createRef 而不是 inline ref 有啥优势?
createRef和useRef区别——useRef的使用——forwardRef完成类组件的绑定—— useImperativeHandle——映射ref对象——更新同步
createRef和useRef区别——useRef的使用——forwardRef完成类组件的绑定—— useImperativeHandle——映射ref对象——更新同步