阅读视图

发现新文章,点击刷新页面。

react-hook-form 初始化值为异步获取的数据的最佳实践

在 React Hook Form 中,直接在 useFormdefaultValues 参数中使用静态默认值是首选方式,因为:

  • defaultValues 是专门设计用于设置表单初始值的,它在钩子初始化时被缓存(cached),性能更好。
  • 它能正确支持 isDirtydirtyFields 等表单状态的计算(以 defaultValues 作为“单一真相来源”)。
  • 官方文档推荐:优先使用 defaultValues 来管理整个表单的默认值,而不是单个输入的 defaultValue

示例:

const { register, handleSubmit } = useForm({
  defaultValues: {
    name: '初始姓名',
    email: 'initial@example.com'
  }
});

但是,如果默认值是异步获取的(如从 API 加载数据),则推荐在 useEffect 中使用 reset(defaultValues)

原因:

  • defaultValues 只在 useForm 初始渲染时读取一次(被缓存),后续 props 或 state 变化不会自动更新表单值。
  • 如果直接把异步数据传给 defaultValues,表单会先渲染为空(或初始空值),然后需要手动重置,导致可能出现“闪烁”(flash)或额外渲染。
  • 使用 reset 可以动态更新表单值,并正确重置表单状态(如清除 errors、touched 等)。

示例(异步加载场景):

const [asyncData, setAsyncData] = useState(null);

useEffect(() => {
  fetch('/api/user').then(res => res.json()).then(data => {
    setAsyncData(data);
  });
}, []);

const { register, reset } = useForm({
  defaultValues: { name: '', email: '' } // 先给空默认值,避免 uncontrolled 警告
});

useEffect(() => {
  if (asyncData) {
    reset(asyncData); // 这里更新表单值
  }
}, [asyncData, reset]);

更现代的推荐(v7+):使用 values prop(而非 defaultValues

从 React Hook Form v7 开始,引入了 values prop,它是响应式的(reactive),会自动在值变化时调用内部 reset,无需手动 useEffect + reset

  • 适合异步数据加载,避免闪烁和额外渲染。
  • defaultValues 仍用于静态初始值,values 用于动态/异步更新。

示例:

const asyncValues = useFetch('/api/user'); // 假设返回 { name: '...', email: '...' }

const { register } = useForm({
  defaultValues: { name: '', email: '' }, // 可选静态初始
  values: asyncValues // 会自动响应变化更新表单
});

总结推荐

场景 推荐方式 原因
静态默认值(已知常量) useForm({ defaultValues: {...} }) 简单、性能好、官方首选
异步默认值(API 等) values prop(首选)
useEffect + reset
values 更优雅、无闪烁;reset 是传统可靠方式
需要手动重置表单 reset(newValues) 可保留/清除特定状态(如 keepDirtyValues)

如果你的默认值是静态的,直接用 defaultValues 最好;如果是动态/异步的,优先试 values,否则用 reset。更多详情可参考官方文档:react-hook-form.com/docs/usefor…

❌