React 19 特性: ref 作为 prop 传递
在 React 19 中,ref 能够作为 prop 直接传递给函数组件,这是一个重要的更新,极大地优化了开发体验。在此之前,我们需要借助 forwardRef 这个高阶组件(HOC)来实现 ref 的转发,而现在这一过程变得更加直观和简洁。
我们来深入探讨这一变化带来的具体优势。
告别 forwardRef 的繁琐
在 React 19 之前,如果想将 ref 附加到我们自己封装的函数组件上,直接在 props 中传递是行不通的。React 会在内部处理 ref,并不会将其作为普通的 prop 传递下去。为了解决这个问题,我们必须使用 React.forwardRef。
旧有的方式:使用 forwardRef
让我们看一个熟悉的例子:创建一个自定义的 MyInput 组件,并希望父组件能获取其底层 input 元素的引用。
import { forwardRef } from 'react';
const MyInput = forwardRef((props, ref) => {
const { label, ...otherProps } = props;
return (
<label>
{label}
<input {...otherProps} ref={ref} />
</label>
);
});
// 使用
function MyForm() {
const inputRef = useRef(null);
function handleFocus() {
inputRef.current.focus();
}
return (
<>
<MyInput ref={inputRef} label="Enter your name" />
<button onClick={handleFocus}>Focus the input</button>
</>
);
}这种写法的核心问题在于:
代码冗余:需要用
forwardRef包裹整个组件。心智负担:
ref是作为第二个参数传入的,这与常规的 props 对象分离,使得组件的签名不统一,增加了理解成本。类型定义复杂:在 TypeScript 中,为使用了
forwardRef的组件正确添加类型定义,往往需要处理复杂的泛型,例如ForwardedRef和RefForwardingComponent。
React 19 的新方式:ref 即 prop
随着 React 19 的到来,ref 终于成为了“一等公民”,可以像其他任何 prop 一样直接传递。上面的 MyInput 组件可以被大大简化。
React 19 的方式:直接作为 prop 传递
// 无需引入 forwardRef
function MyInput({ label, ref, ...otherProps }) {
return (
<label>
{label}
<input {...otherProps} ref={ref} />
</label>
);
}
// 使用方式完全相同
function MyForm() {
const inputRef = useRef(null);
function handleFocus() {
inputRef.current.focus();
}
return (
<>
<MyInput ref={inputRef} label="Enter your name" />
<button onClick={handleFocus}>Focus the input</button>
</>
);
}代码变得清晰直白,就像我们直觉上认为的那样工作。
核心优势总结
将 ref 作为 prop 直接传递,主要带来了以下几点优势:
代码更简洁,可读性更高我们不再需要forwardRef的包裹。组件定义更加紧凑,逻辑也更聚焦于组件本身,而不是如何处理 ref 转发的模板代码。降低心智负担,提升开发体验ref只是 props 里的一个普通属性。这统一了组件的接口,开发者不再需要记忆forwardRef的特殊签名和用法。无论是初学者还是经验丰富的开发者,都能更快地编写和理解代码。简化组件组合当 ref 需要穿透多层组件时,优势尤为明显。每一层组件只需要简单地将ref从props中取出再传递给下一层即可,不再需要层层嵌套forwardRef,代码的整洁度大幅提升。与 TypeScript 集成更友好为refprop 添加类型定义变得非常简单。我们可以像定义其他prop一样,直接在组件的props类型接口中声明ref。
import type { Ref } from 'react';
type MyInputProps = {
label: string;
ref: Ref<HTMLInputElement>;
// 其他 props...
};
function MyInput({ label, ref, ...otherProps }: MyInputProps) {
// ...
}相比之下,forwardRef 的类型定义要繁琐得多,经常需要开发者花费额外精力去查阅文档或处理复杂的泛型。
结论
总而言之,React 19 将 ref 作为 prop 传递的改动,是一项意义重大的 “Quality of Life” 更新。它移除了一个长期以来困扰开发者的冗余模式,使 ref 的处理回归到 props 模型的统一心智模型中。这不仅让代码变得更加干净、直观,也显著降低了编写和维护可复用组件时的复杂性,是 React 团队在提升开发者体验方面迈出的坚实一步。
