React中组件被父组件调用两次时useRef的工作机制疑问
问题原因分析
你遇到的现象核心原因是**useRef的声明位置错误**,导致多个MyInput组件实例共享了同一个ref对象,而非各自持有独立的ref。
错误写法的问题所在
如果你的代码是类似这样的:
// 错误:ref声明在组件外部,全局共享 const inputRef = useRef(null); function MyInput() { useEffect(() => { inputRef.current.focus(); }, []); return <input ref={inputRef} />; }
- 这里的
inputRef是定义在MyInput组件函数之外的,属于全局作用域变量。 - 第一个
MyInput渲染时,inputRef.current会被赋值为第一个输入框的DOM元素;第二个MyInput渲染时,inputRef.current会被覆盖为第二个输入框的DOM元素。 - 最终所有effect执行时,只会对最后一次赋值的DOM元素(第二个输入框)调用
focus(),所以只有它获得焦点。
正确的实现方式
要让每个组件实例拥有独立的ref,必须把useRef的声明放在组件函数内部:
// 正确:ref声明在组件内部,每个实例独立持有 function MyInput() { const inputRef = useRef(null); // 每个MyInput实例都会创建自己的inputRef useEffect(() => { inputRef.current.focus(); }, []); return <input ref={inputRef} />; }
- 此时每个
MyInput组件实例在渲染时,都会创建属于自己的inputRef对象,分别绑定各自的输入框DOM节点。 - 每个实例的effect都会调用自己ref对应的
focus()方法,因此两个输入框都会获得焦点。
补充说明
React的useRef是组件实例级别的钩子,只有当它在组件函数内部被调用时,React才会为每个组件实例分配独立的ref存储空间。如果放在组件外部,就失去了这种实例隔离的特性,变成了普通的共享变量。
内容的提问来源于stack exchange,提问作者crab xie
相关产品推荐
相关产品推荐

