React函数组件中useRef Hook创建ref的原理与用法咨询
useRef 实现原理与用法说明
首先纠正一个认知偏差:你之前了解的「函数组件无法创建引用」是不准确的。
真正的问题是:如果在函数组件里直接调用React.createRef(),每次组件重渲染都会执行一遍函数逻辑,生成全新的ref对象,之前绑定的DOM引用、存储的值都会丢失,根本没法跨渲染周期保留内容——不是函数组件不能创建ref,是普通的createRef在函数组件场景下没法持久保存ref内容。
useRef能在函数组件里稳定创建、持有ref,核心逻辑非常简单:
- React会为每个函数组件对应一个独立的Fiber节点,节点上预留了专门的记忆存储槽位
- 组件首次挂载渲染调用
useRef(初始值)时,React会生成一个结构为{ current: 初始值 }的普通JS对象,把这个对象存在对应的记忆槽位里,再返回给调用方 - 后续组件每次重渲染再调用useRef时,React不会生成新对象,会直接把记忆槽位里存的同一个对象返回
- 这个返回的对象引用在组件整个生命周期里永远不会变,你可以随时读写它的
current属性存任意值(包括DOM节点、定时器ID、普通变量等),修改current属性不会触发组件重渲染
结合你提供的示例代码,整个执行流程是:
- 组件首次渲染时,
useRef()返回{ current: undefined },赋值给inputElement变量 - React渲染真实DOM阶段,解析到input标签上的
ref={inputElement}属性,会把生成的真实input DOM节点赋值给inputElement.current - 点击按钮触发
focusInput时,直接通过inputElement.current拿到input DOM实例,调用它的focus()方法触发聚焦 - 不管组件后续重渲染多少次,
inputElement永远指向首次渲染创建的那个ref对象,上面存的DOM引用不会丢失
import "./styles.css"; import {useRef} from "react"; const App = () => { const inputElement = useRef(); const focusInput = () => { inputElement.current.focus(); }; return ( <> <input type="text" ref={inputElement} /> <button onClick={focusInput}>Focus Input</button> </> ); } export default App;
额外注意一个容易混淆的点:函数组件本身不能直接作为ref的绑定目标(因为函数组件没有类组件那样的组件实例),但这和函数组件内部能不能创建、使用ref是两回事,useRef就是专门为函数组件提供的跨渲染周期持有可变值的能力。
内容的提问来源于stack exchange,提问作者Ateev Duggal
相关产品推荐
相关产品推荐

