490 字
2 分钟
React 19 的 ref 作为 prop

19 之前必须包一层#

在 React 18 里,ref 是特殊 prop,函数组件收不到它。要让父组件拿到内部的 DOM 节点,得用 forwardRef 把 ref 转发进来:

// 18 写法
const MyInput = forwardRef(function MyInput(props, ref) {
return <input {...props} ref={ref} />
})

这一层壳的唯一作用就是「让 ref 通过」。

19 起它就是个普通 prop#

// 19 写法
function MyInput({ value, onChange, ref }) {
return <input value={value} onChange={onChange} ref={ref} />
}

官方发布说明里的原话是:函数组件可以直接把 ref 当 prop 访问,新的函数组件不再需要 forwardRef(React 19 发布说明)。

forwardRef 还没有删除,但参考页上已经挂了弃用横幅。读旧代码时会见到它,新代码不必再写。

一个例外:类组件收到的 ref 仍然是组件实例,不会作为 prop 传进去。

ref 回调可以返回清理函数#

19 起,ref 回调允许返回一个清理函数,卸载时 React 调用它:

<div
ref={node => {
const observer = new ResizeObserver(() => {})
observer.observe(node)
return () => observer.disconnect()
}}
/>

旧写法是在回调里判断 node === null 来做清理。官方说将来会弃用「卸载时以 null 调用 ref 回调」这种做法,新代码用返回清理函数的形式。

TypeScript 上有个细节:返回值必须是清理函数(或什么都不返回)。ref={c => (instance = c)} 会被拒,因为它返回了赋值结果;写成块体 ref={c => { instance = c }} 就对了。

19.3 起 Fragment 也能收 ref#

React 19.3 给 <Fragment> 加了 ref,拿到的是一个 FragmentInstance,可以在它上面添加事件监听、读取子节点位置。需要给一组相邻元素整体挂监听或量位置时有用(React 19.3)。

与相邻几篇的关系#

useRef 本身怎么用、什么时候不该用,见 useRef;要定制「父组件能拿到什么」,用 useImperativeHandle,见 useImperativeHandle;forwardRef 退场之后,高阶组件只要透传 props 就顺带带上了 ref,见 高阶组件(HOC)。

第 15 篇,共 39 篇本文属于系列

React 19 的 ref 作为 prop
https://www.choria.top/posts/react-ref-as-prop/
作者
乔瑞雅·克林威尔
发布于
2026-05-02
许可协议
CC BY-NC-SA 4.0

分享文章

生成精美分享图或复制链接,与更多人分享本文。

继续阅读

沿着主题读

基于共同的标签与分类

换条路线

从其他文章中稳定抽取

最后更新于 ,距今已过 190 天

部分内容可能已过时