如何在使用useForm校验表单时配合localStorage持久化数据
问题根源
react-hook-form的register方法会自动给输入框注入内部状态同步需要的onChange、ref、name属性,你手动给input加的value属性、自定义handleChange事件会覆盖这些注入逻辑,导致表单库内部拿不到最新的输入值,校验逻辑自然失效。- 你额外维护的
values状态属于重复逻辑:react-hook-form本身就内置了表单状态管理、默认值注入、值变更监听能力,完全不需要自己再写一套状态同步逻辑对接localStorage。
修复实现
直接用useForm自带的能力对接持久化即可,不需要单独维护表单state:
- 初始化
useForm时,通过defaultValues配置项直接读取localStorage的缓存值作为表单初始值,实现刷新后自动回填 - 用
watch方法监听全表单的值变化,值变更时自动同步到localStorage - 输入框只需要绑定
register即可,不需要手动写value属性和自定义onChange处理,校验规则直接写在register的第二个参数中就能正常触发
完整可运行代码:
import React, { useEffect } from "react"; import "./App.css" import { useForm } from "react-hook-form"; // 读取localStorage缓存的表单值 const getStoredForm = () => { const storedValues = localStorage.getItem("form"); if(!storedValues) return { name: "", age: "" } return JSON.parse(storedValues); } function Home() { const { register, handleSubmit, watch, formState: { errors } } = useForm({ // 初始化直接用缓存值作为默认值 defaultValues: getStoredForm() }); const onSubmit = async data => { console.log("提交的表单数据", data); }; // 监听所有表单值变化,自动同步到localStorage const allFormValues = watch() useEffect(()=>{ localStorage.setItem("form", JSON.stringify(allFormValues)) }, [allFormValues]) return ( <div className="container"> <form onSubmit={handleSubmit(onSubmit)}> <div> <input {...register("name", { required: "姓名不能为空" })} placeholder="请输入姓名" /> {/* 校验错误提示 */} {errors.name && <span style={{color: 'red'}}>{errors.name.message}</span>} </div> <div> <input {...register("age", { required: "年龄不能为空", min: { value: 1, message: "年龄不能小于1岁" }, valueAsNumber: true })} placeholder="请输入年龄" /> {errors.age && <span style={{color: 'red'}}>{errors.age.message}</span>} </div> <button type="submit">提交</button> </form> </div> ) } export default Home;
补充说明
如果你后续有特殊的输入控制需求(比如输入内容实时格式化、对接第三方自定义输入组件),不要手动覆盖register注入的属性,改用react-hook-form提供的Controller组件或者useController钩子对接受控组件即可,不会破坏内部的状态同步和校验逻辑。
内容的提问来源于stack exchange,提问作者ceaiius
相关产品推荐
相关产品推荐

