React Hook Form无法填充获取到的数据问题排查
问题分析与解决方案
你的表单无法正确渲染初始数据,核心原因是react-hook-form 的 useForm 仅在组件初始化时读取一次 defaultValues,如果数据是异步加载(比如从 Redux 或 API 获取),后续数据更新不会自动同步到表单中。即使你通过 return data && (...) 控制渲染时机,若初始传入的 data 是空对象(而非 undefined),表单仍会以空值初始化,后续数据更新也不会触发表单值的刷新。
具体修复步骤
- 引入
reset方法:从useForm中解构出reset函数,用于手动重置表单值。 - 监听数据变化并重置表单:使用
useEffect监听dataProp 的变化,每当数据更新时调用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
相关产品推荐
相关产品推荐

