You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Hook Form无法填充获取到的数据问题排查

问题分析与解决方案

你的表单无法正确渲染初始数据,核心原因是react-hook-form 的 useForm 仅在组件初始化时读取一次 defaultValues,如果数据是异步加载(比如从 Redux 或 API 获取),后续数据更新不会自动同步到表单中。即使你通过 return data && (...) 控制渲染时机,若初始传入的 data 是空对象(而非 undefined),表单仍会以空值初始化,后续数据更新也不会触发表单值的刷新。

具体修复步骤

  1. 引入 reset 方法:从 useForm 中解构出 reset 函数,用于手动重置表单值。
  2. 监听数据变化并重置表单:使用 useEffect 监听 data Prop 的变化,每当数据更新时调用 reset 同步表单值。

修改后的 DescriptionForm 代码如下:

import * as React from "react";
import { useForm, SubmitHandler, Controller } from "react-hook-form";
import { Char } from "../../models";
import { strikerTheme } from "../../../shared/components/StrikerTheme";
import ThemeProvider from "@mui/material/styles/ThemeProvider";
import TextField from "@mui/material/TextField";
import MenuItem from "@mui/material/MenuItem";
import InputAdornment from "@mui/material/InputAdornment";
import { useAppSelector } from "../../../../app/hooks";
import { getTraits, getIdeals } from "../../../shared/specSlice";
import { Quality } from "../../models/specs";
import { CheckboxGroup } from ".";


export const DescriptionForm = ({
  onSubmit,
  data
}: {
  data: Partial<Char>;
  onSubmit: SubmitHandler<Partial<Char>>;
}) => {

  const specState = useAppSelector(state => state.specState);
  const { handleSubmit, control, reset } = useForm({defaultValues: data});

  // 监听data变化,同步表单值
  React.useEffect(() => {
    if (data) {
      reset(data);
    }
  }, [data, reset]);

  const alignments = ['Lawful Good', 'Neutral Good', 'Chaotic Good', 'Lawful Neutral', 'Neutral', 'Chaotic Neutral', 'Lawful Evil', 'Neutral Evil', 'Chaotic Evil']
  const traits: Quality[] = getTraits(specState.specKeys);
  const ideals: Quality[] = getIdeals(specState.specKeys);


  return data && (
    <ThemeProvider theme={strikerTheme}>
      <form className='form' onSubmit={handleSubmit(onSubmit)}>
        <h4>Description</h4>
        <div className='form-row'>
          <Controller name="name" control={control} render={({ field }) => <TextField sx={{ width: '40ch' }} {...field} label="character name" />} />
        </div>
        <div className='form-row'>
          <Controller name="experience" control={control} render={({ field }) => <TextField {...field} label="experience" />} />
          <Controller name="levels" control={control} render={({ field }) => <TextField {...field} label="level" />} />
        </div>
        <div className='form-row'>
          <Controller name="age" control={control} render={({ field }) => <TextField {...field} label="age" />} />
          <Controller name="gender" control={control} render={({ field }) => <TextField {...field} label="gender" />} />
          <Controller name="height" control={control} render={({ field }) => <TextField {...field} label="height" />} />
          <Controller name="weight" control={control} render={({ field }) =>
            <TextField {...field} label="weight" InputProps={{
              endAdornment: <InputAdornment position="end">kg</InputAdornment>,
            }}
            />}
          />
        </div>
        <div className='form-row'>
          <Controller
            name="alignment"
            control={control}
            render={({ field }) => <TextField {...field} label="alignment" helperText="Please select your alignment" select>
              {alignments.map((option) => (
                <MenuItem key={option} value={option}>
                  {option}
                </MenuItem>
              ))}
            </TextField>}
          />
          <div className='form-row'>
            <Controller name="traits" control={control} render={({ field }) => <CheckboxGroup
              control={control}
              label="traits"
              options={traits}
              {...field}
            />
            } />
          </div>

          <div className='form-row'>
            <Controller name="ideals" control={control} render={({ field }) => <CheckboxGroup
              control={control}
              label="ideals"
              options={ideals}
              {...field}
            />
            } />
          </div>
        </div>
        <button
          type='submit'
          className='btn btn-block btn-danger'
        >
          Submit
        </button>
      </form>
    </ThemeProvider>
  )
};

额外检查项

  • 确保 data 对象的键名与所有 Controller 的 name 属性完全匹配(大小写敏感)。
  • 验证自定义组件 CheckboxGroup 正确接收并处理 value 和 onChange 属性(用于渲染多选框的选中状态)。
  • 若 data 初始为空对象,可将渲染条件改为 Object.keys(data).length > 0 && (...),避免表单提前初始化。

内容的提问来源于stack exchange,提问作者Michael Coxon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 13:49:53