React中useForm的handleSubmit调用sendData报错求助
解决react-hook-form中handleSubmit使用错误及机制说明
原本有一个可正常向JSON文件创建新记录的sendData函数,运行一切正常。但添加useForm结合yup校验器后,在
handleSubmit工作机制
handleSubmit是react-hook-form的核心函数,作用是接管表单的提交流程:- 自动阻止表单默认提交行为(无需手动写
event.preventDefault()) - 触发yup校验逻辑
- 校验通过时,调用第一个参数(成功回调函数),并将校验后的表单数据作为参数传入该函数
- 校验不通过时,调用第二个可选参数(失败回调函数),传入错误信息
- 自动阻止表单默认提交行为(无需手动写
- 注意:传给
handleSubmit的必须是函数引用,不能是函数调用的结果(比如不能写sendData(),要写sendData)
错误原因分析
- 错误调用handleSubmit:
handleSubmit(sendData(), onSubmit)中,sendData()是直接执行函数,导致组件渲染时就触发了sendData,而且handleSubmit接收的是sendData的返回值(undefined),不是可执行的函数,提交时自然报错。 - 重复维护表单状态:手动用useState维护
details状态,同时又用react-hook-form的register,两者状态不同步,既冗余又容易出问题——react-hook-form本身会自动管理表单状态,不需要手动维护。
修复后的代码
import React, { useState } from 'react'; import { useForm } from 'react-hook-form'; import { useNavigate } from 'react-router-dom'; import Confirmation from './Confirmation'; import * as yup from 'yup'; import { yupResolver } from '@hookform/resolvers/yup'; const schema = yup.object().shape({ name: yup.string().required('姓名不能为空'), age: yup.number().positive('年龄必须为正数').required('年龄不能为空'), salary: yup.number().positive('薪资必须为正数').required('薪资不能为空'), email: yup.string().email('请输入合法邮箱').required('邮箱不能为空'), }).required(); export default function LogIn() { const { register, handleSubmit, formState: { errors } } = useForm({ resolver: yupResolver(schema), }); const navigate = useNavigate(); const [show, setShow] = useState(false); // 接收react-hook-form传递的校验后的数据 const sendData = async (data) => { const res = await fetch("你隐藏的接口地址", { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) // 直接用校验后的data }); navigate("/main"); }; const onSubmitFailed = (errors) => { console.log('校验失败:', errors); }; return ( <div> {show && <Confirmation show={show} setShow={setShow} />} <div className="form-center"> <h1>填写基本信息</h1> {/* 正确传递函数引用给handleSubmit */} <form onSubmit={handleSubmit(sendData, onSubmitFailed)}> <div className="form-controll"> <input type="text" {...register('name')} placeholder="Name" /> {errors.name && <p>{errors.name.message}</p>} <input type="number" {...register('age')} placeholder="Age" /> {errors.age && <p>{errors.age.message}</p>} <input type="number" {...register('salary')} placeholder="Salary in $" /> {errors.salary && <p>{errors.salary.message}</p>} <input type="email" {...register('email')} placeholder="Email" /> {errors.email && <p>{errors.email.message}</p>} </div> <div className="forgot"> Don't want to share data?<br></br> <button type="button" onClick={() => setShow(true)}>Ghost mode</button> </div> <div className="btn"> <input type='submit' value='Go' /> </div> </form> </div> </div> ); }
关键修复点
- 移除了手动维护的
details状态,直接使用react-hook-form传递的校验后的数据 - 将
handleSubmit(sendData(), onSubmit)改为handleSubmit(sendData, onSubmitFailed),传递函数引用而非调用结果 - 移除了input上的onChange事件,register会自动更新表单状态
- 给yup规则添加了自定义错误提示,提升用户体验
- 给"Ghost mode"按钮添加了
type="button",避免触发表单提交
内容的提问来源于stack exchange,提问作者srmback
相关产品推荐
相关产品推荐

