本文详解为何不能直接将 useref 对象作为 props 传入普通函数组件,以及如何通过 forwardref 实现安全、符合 react 惯例的 ref 透传。
本文详解为何不能直接将 useref 对象作为 props 传入普通函数组件,以及如何通过 forwardref 实现安全、符合 react 惯例的 ref 透传。
在 React 开发中,useRef 创建的 ref 对象常用于访问 DOM 元素或保存可变值。但当尝试将其直接作为 props(如 todoRef={todoRef})传给子组件时,虽然代码看似“能运行”,实则违反了 React 的 ref 传递机制——普通函数组件默认不支持接收 ref,React 会静默忽略该 prop,不会报错,也不会建立实际的 ref 绑定。
上述示例中,InputField 是一个普通无 ref 函数组件,它内部虽写了 ref={todoRef},但由于未启用 ref 转发,todoRef.current 在父组件中始终为 null(或初始值),导致 todoRef.current.value 实际读取失败——你观察到的“正常工作”很可能是因浏览器缓存、输入框聚焦状态残留或调试时机偏差造成的假象;严格测试(如在 onFormSubmit 中添加 console.log(todoRef.current))会暴露其为空。
✅ 正确做法是使用 forwardRef 显式启用 ref 转发:
import { forwardRef } from 'react';const InputField = forwardRef(function InputField({ onFormSubmit }, ref) { return ( <form onSubmit={onFormSubmit}> <input type="text" name="task" placeholder="What task needs to be completed?" ref={ref} // ✅ ref 现在被正确接收并绑定到 input /> </form> );});
注意:forwardRef 接收一个双参数函数(props 和 ref),并将 ref 作为第二个参数显式注入;子组件内部必须将该 ref 赋给具体的 DOM 元素(如 <input ref={ref} />)。此时父组件的 useRef 才能真正关联到子组件中的 input 实例。
⚠️ 重要注意事项:
总结:forwardRef 不是“高级技巧”,而是函数组件参与 ref 体系的标准契约。跳过它而强行 props 传 ref,属于反模式:表面可行,实则脆弱、不可靠、难以调试。养成习惯——只要涉及 ref 透传,第一步必写 forwardRef。