react 的 ref 回调函数在 dom 元素挂载时接收真实节点,在卸载时接收 null,这是 react 保证 ref 状态与 dom 生命周期严格同步的机制,并非类型错误或 bug。
在使用函数式 ref(如 ref={el => ...})时,React 会主动且确定地在两个关键时机调用该回调:
✅ 挂载时:DOM 元素成功插入文档后,传入对应的 HTMLInputElement 实例;
❌ 卸载时:元素被移除(例如数组长度变化、条件渲染导致组件消失、父组件重渲染等),React 会再次调用该 ref 回调,并传入 null —— 这是为了显式通知你“该引用已失效”,避免悬挂引用(dangling reference)和内存泄漏。
因此,你代码中 el: HTMLInputElement | null 的类型是完全正确且必要的。若忽略 null 分支,直接赋值 inputsRef.current[i] = el,虽然运行时通常无异常,但会在元素卸载后将 null 写入数组,后续若未做空值检查就调用 inputsRef.current[i]?.focus() 等方法,将导致静默失败或运行时错误。
✅ 正确写法(安全、健壮):
export default function SomeArray() {
const inputsRef = useRef([]);
return (
<>
{[1, 2, 3].map((_, i) => (
{
if (el) {
// 挂载:存入有效节点
inputsRef.current[i] = el;
} else {
// 卸载:清理对应位置,避免残留 null 或旧节点
inputsRef.current[i] = null;
}
}}
/>
))}
>
);
} ? 关键注意事项:
const firstValid = inputsRef.current.find(el => el !==null); firstValid?.focus();
总结:null 不是“意外”,而是 React 的契约式设计——它赋予你精确控制引用生命周期的能力。拥抱 HTMLInputElement | null 类型,主动处理 null 分支,是编写可维护、可预测 React DOM 交互代码的必要实践。