React使用useRef实现可切换表单输入框自动聚焦问题求解
问题根因
你遇到的报错核心有两个原因:
react-hook-form的register()方法返回的对象中自带ref属性,你将{...register("newVal")}写在ref={field}之后,会直接覆盖你自定义的ref赋值,导致field.current永远为null- 状态变更后
useEffect触发时机早于浏览器完成DOM样式更新的时机,即使拿到ref,此时表单还处于display: none状态,聚焦也会失效
解决方案
第一步:正确注册自定义ref
修改input的属性写法,把你的自定义ref传入register的配置项,避免被覆盖:
<input type={props.inputType} {...register("newVal", { ref: field })} />
第二步:调整聚焦逻辑的执行时机
用requestAnimationFrame包裹聚焦逻辑,等待浏览器完成DOM渲染、样式生效后再执行聚焦,同时加上可选链避免边界报错:
useEffect(() => { if (mebOpen) { requestAnimationFrame(() => { field.current?.focus() }) } }, [mebOpen])
如果仍有时序问题,可以把useEffect换成useLayoutEffect,它会在DOM更新完成后、浏览器绘制前同步执行,更适配DOM操作类的需求。
关于forwardRef的疑问
当前场景不需要使用forwardRef,它的作用是父组件跨层级传递ref到子组件内部的DOM元素,你所有操作都在同一个EditBox组件内完成,没有跨组件传递ref的需求,不需要学习它来解决当前问题。
内容的提问来源于stack exchange,提问作者McKayB
相关产品推荐
相关产品推荐

