TS-React项目中react-hook-form提交后如何让输入框失焦
实现方案
你无法定位输入框的核心原因是:在Controller的render方法中解构field属性时,单独拆分出了ref字段但没有绑定到InputText组件上,导致表单实例没有持有输入框的DOM引用,自然无法在提交回调中触达目标元素。
以下提供两种可直接落地的实现方式:
方案1:自定义Ref绑定(兼容性最好,推荐)
使用React原生useRef创建输入框引用,同时兼容react-hook-form的内部ref绑定逻辑,不破坏原有表单校验、值同步能力,提交时直接调用ref上的blur方法即可:
import { FC, useRef } from "react"; import { Controller, useForm } from "react-hook-form"; // 提前定义好表单类型避免any type Basket = { scanId: string; } const BasketContainer: FC = () => { // 新增扫描输入框的DOM引用 const scanIdInputRef = useRef<HTMLInputElement>(null); const { control, handleSubmit, setValue, watch, getValues, reset, formState: {errors} } = useForm<Basket>({ defaultValues: { scanId: "" } }); const handleScanIdSubmit = (data: Basket) => { // 这里写原有fetch请求、业务处理逻辑 // 所有逻辑执行完成后触发输入框失焦 scanIdInputRef.current?.blur(); }; return ( <form onSubmit={handleSubmit(handleScanIdSubmit)}> <Controller control={control} name="scanId" rules={{required: "Field required"}} render={({field: {ref, ...restField}}) => ( <InputText {...restField} // 同时绑定rhf内部ref和自定义ref,不影响原有表单逻辑 ref={(element) => { ref(element); scanIdInputRef.current = element; }} type="text" label="ID" errorMessage={errors.scanId?.message} /> )} /> <Button type="submit" /> </form> ); };
注意:如果你的
InputText是自定义组件,需要确认组件做了forwardRef透传,才能拿到真实的input DOM节点。如果组件未做ref透传,可以给输入框加固定id,提交时通过document.getElementById("scan-id-input")?.blur()实现效果,只是这种方式优先度低于ref方案。
方案2:直接透传Controller提供的ref
如果不需要自定义持有ref,直接把Controller field里的所有属性全量传给InputText即可,提交时可以通过react-hook-form的字段引用触发blur:
// Controller部分修改为全量透传field <Controller control={control} name="scanId" rules={{required: "Field required"}} render={({field}) => ( <InputText {...field} type="text" label="ID" errorMessage={errors.scanId?.message} /> )} />
提交回调里通过表单内部字段引用触发失焦:
const handleScanIdSubmit = (data: Basket) => { // 原有业务逻辑 // 触发字段失焦 control._fields.scanId?._f.ref?.blur(); };
这个写法依赖react-hook-form的内部属性结构,版本升级时可能有变动,优先选择方案1。
内容的提问来源于stack exchange,提问作者KaraStras J.B
相关产品推荐
相关产品推荐

