
本文详解如何正确使用 useRef 与 React.forwardRef 在组件首次渲染后读取 DOM 节点(如 input)的初始值,避免因 ref 未正确转发导致的 null 或警告问题。
本文详解如何正确使用 `useref` 与 `react.forwardref` 在组件首次渲染后读取 dom 节点(如 input)的初始值,避免因 ref 未正确转发导致的 `null` 或警告问题。
在 React 函数组件中,若需在初始渲染后访问原生 DOM 元素(例如获取 的 defaultValue 或当前值),必须确保 ref 被正确传递并绑定到实际 DOM 节点上。你遇到的错误——"ref is not a prop" 和 name 输出为 null——根本原因在于:普通函数组件无法直接接收并转发 ref;必须显式使用 React.forwardRef。
✅ 正确做法:用 forwardRef 包裹子组件
FormRow 是一个自定义封装组件,它内部渲染 ,但默认不支持 ref 透传。你需要将其改写为 forwardRef 组件,并将 ref 参数直接绑定到 上:
import React from "react";
const FormRow = React.forwardRef(
({ type, name, labelText, defaultValue = "", onChange, onBlur, max }, ref) => {
return (
<div classname="form-row">
<label htmlfor="{name}" classname="form-label">
{labelText || name}
</label>
<input autocomplete="off" type="{type}" id="{name}" name="{name}" classname="form-input" defaultvalue="{defaultValue}" required onchange="{onChange}" onblur="{onBlur}" max="{max}" min="0" ref="{ref}" input>
</div>
);
}
);
export default FormRow;
⚠️ 注意:forwardRef 的第二个参数是 ref,它不是 props 的一部分,因此不能解构到 { ref } 中——必须作为独立参数接收。
✅ 在父组件中安全读取 DOM 值
在 AddProject 中,useRef 创建的引用对象本身不是值,而是包含 .current 属性的对象。且 useEffect 必须添加空依赖数组 [],确保只在挂载后执行一次(即“初始渲染后”):
const AddProject = () => {
const refContainer = useRef(null);
useEffect(() => {
// ✅ 确保 DOM 已挂载,且 ref 已绑定
if (refContainer.current) {
console.log("Initial input value:", refContainer.current.value); // 输出 defaultValue="1"
// 也可读取其他属性,如 refContainer.current.defaultValue
}
}, []); // ? 依赖数组为空,仅执行一次
return (
<wrapper><form>
<formrow type="number" name="noOfChemicals" labeltext="Number of Chemicals / Work Items" onchange="{handleChange}" defaultvalue="1" ref="{refContainer}"></formrow>
</form>
</wrapper>
);
};
export default AddProject;
? 关键要点总结
- ref 不是普通 prop,不可在解构参数中直接写 { ref },必须用 forwardRef 显式接收;
- useRef().current 初始为 null,务必在 useEffect 中检查 ref.current 是否存在,再访问其属性(如 .value, .defaultValue);
- 若需读取 defaultValue(即初始设定值),可用 refContainer.current.defaultValue;若需读取渲染后实际显示的值(含用户未修改前的状态),用 .value 即可;
- useEffect 的依赖数组 [] 是保证“仅初始渲染后执行”的关键,避免重复执行或竞态问题。
遵循以上模式,即可稳健、清晰地在 React 中实现 DOM 值的初始读取。











