React Hook Form结合Yup动态创建输入框聚焦异常问题求解
解决React Hook Form动态字段添加后焦点跳转问题
要实现点击添加按钮后,焦点自动落在最后一个动态创建的输入框上,可通过ref数组追踪动态输入框并在字段更新后手动触发焦点,具体步骤如下:
1. 创建ref数组存储动态输入框引用
在组件内部定义一个ref数组,用于记录每个动态生成的配料名称输入框的DOM引用:
const ingredientRefs = useRef([]);
2. 绑定ref到动态输入框
在渲染动态配料字段的Controller组件中,将每个输入框的ref存入数组:
{watch("ingredients").map((_, index) => ( <div key={index} className="flex gap-2 mb-2"> <Controller name={`ingredients.${index}.name`} control={control} rules={{ required: true }} render={({ field }) => ( <input {...field} // 将当前输入框的ref存入数组对应索引位置 ref={(el) => { ingredientRefs.current[index] = el; }} type="text" placeholder="配料名称" className="border p-2 flex-1" /> )} /> <Controller name={`ingredients.${index}.quantity`} control={control} rules={{ required: true }} render={({ field }) => ( <input {...field} type="text" placeholder="数量" className="border p-2 w-24" /> )} /> </div> ))}
3. 监听字段变化并触发焦点
使用useEffect监听配料数组的变化,当数组长度增加(即添加新字段)时,聚焦最后一个输入框:
useEffect(() => { const ingredients = watch("ingredients"); // 获取最后一个输入框的索引 const lastIndex = ingredients.length - 1; if (lastIndex >= 0) { // 确保DOM已更新后再触发焦点 requestAnimationFrame(() => { ingredientRefs.current[lastIndex]?.focus(); }); } }, [watch("ingredients")]);
原理说明
- 通过
ref数组精准追踪每个动态输入框的DOM元素,避免React渲染后丢失引用 - 使用
requestAnimationFrame确保React完成DOM更新后再执行焦点操作,解决异步渲染导致的ref未就绪问题 - 手动触发焦点会覆盖浏览器默认的焦点跳转行为,确保焦点落在目标输入框上
内容的提问来源于stack exchange,提问作者Oshri Moalem
相关产品推荐
相关产品推荐

