React Hook Form表单变化时useEffect未触发的原因及解决方法
问题原因分析
你提供的示例里,useEffect的触发依赖是reset函数和student状态,但用户填写表单时,表单数据存在React Hook Form的内部状态中,并没有更新你定义的student状态,所以依赖项没有变化,自然不会触发这个useEffect。原示例中的useEffect只是用来在student初始化后重置表单值,并非用于监听用户输入。
实时监听表单数据的方法
React Hook Form自带watch API,专门用来监听表单字段的变化,结合useEffect就能实现实时监听需求:
方法1:监听所有表单字段
通过watch()获取所有表单字段的实时值,再在useEffect中监听这个值的变化:
import React, { useState, useEffect } from "react"; import { useForm } from "react-hook-form"; export default function SimpleForm() { const { register, handleSubmit, reset, formState, watch } = useForm(); const [student, initStudent] = useState(null); // 监听所有表单字段的实时值 const formValues = watch(); useEffect(() => { setTimeout( () => initStudent({ name: "Little Johnny", email: "lil@johnny.com", grade: "3rd", }), 1200 ); }, []); useEffect(() => { console.log("updating.,.."); reset(student); }, [reset, student]); // 实时监听表单数据变化 useEffect(() => { console.log("表单数据实时变化:", formValues); // 这里可以添加你需要的业务逻辑 }, [formValues]); function onFormSubmit(dataRes) { console.log(dataRes); return false; } return ( <div> <h2 className="mb-3"> React Initiate Form Values in useEffect Hook Example </h2> {student && ( <form onSubmit={handleSubmit(onFormSubmit)}> <div className="form-group mb-3"> <label>Name</label> <input type="text" name="name" {...register("name")} className="form-control" /> </div> <div className="form-group mb-3"> <label>Email</label> <input type="email" name="email" {...register("email")} className="form-control" /> </div> <div className="form-group mb-3"> <label>Grade</label> <input type="text" name="grade" {...register("grade")} className="form-control" /> </div> <button type="submit" className="btn btn-dark"> Send </button> </form> )} {!student && ( <div className="text-center p-3"> <span className="spinner-border spinner-border-sm align-center"></span> </div> )} </div> ); }
方法2:监听单个/指定字段
如果只需要关注特定字段,比如name,可以针对性监听:
const nameValue = watch('name'); useEffect(() => { console.log("姓名变化了:", nameValue); }, [nameValue]);
如果要监听多个指定字段,用数组传入即可:
const [nameValue, emailValue] = watch(['name', 'email']); useEffect(() => { console.log("姓名或邮箱变化了:", nameValue, emailValue); }, [nameValue, emailValue]);
补充说明
watch会返回当前表单字段的实时值,用户每次输入都会更新这个值,因此对应的useEffect会同步触发。- 若需要监听表单的“是否被修改”状态,可以使用
formState.dirtyFields,它会记录所有被修改过的字段,同样可以放到useEffect的依赖中监听。
内容的提问来源于stack exchange,提问作者user3226932
相关产品推荐
相关产品推荐

