使用MUI+React Hook Form时,TextField赋值后无法修改的解决方法
MUI TextField结合React Hook Form无法修改数据的解决方法
问题场景
封装了CustomTextField.tsx结合MUI与React Hook Form使用,父组件需要实现:
- 显示获取到的初始数据
- 修改TextField中的文本
- 提交修改后的新值
当前实现能显示初始数据,但无法修改文本,且提交数据与界面显示不一致。
问题原因
直接给CustomTextField传递value={fetchedData}会覆盖React Hook Form中Controller管理的表单值,导致onChange无法更新内部状态——TextField的值被固定为外部的fetchedData,自然无法修改,提交时也只能拿到表单的初始空值或旧值。
解决方案
1. 修正CustomTextField组件
让表单值完全由React Hook Form的Controller管理,不要从外部传入value,同时优化类型约束和错误处理:
// CustomTextField.tsx import { TextField } from "@mui/material"; import { Controller, Control, FieldValues } from "react-hook-form"; type CustomTextFieldProps<T extends FieldValues> = { name: keyof T; control: Control<T>; } & Omit<React.ComponentProps<typeof TextField>, "name" | "onChange" | "value">; export default function CustomTextField<T extends FieldValues>(props: CustomTextFieldProps<T>) { const { control, name, ...rest } = props; return ( <Controller name={name as string} control={control} render={({ field: { onChange, value }, fieldState: { error } }) => ( <TextField onChange={onChange} value={value} error={!!error} helperText={error?.message} {...rest} /> )} /> ); }
2. 父组件中用reset初始化表单值
使用React Hook Form提供的reset方法,在获取到数据后初始化表单,而不是直接给组件传value:
// App.tsx import { useState, useEffect } from "react"; import { useForm } from "react-hook-form"; import CustomTextField from "./CustomTextField"; type FormValues = { description: string; }; export default function App() { const { control, handleSubmit, reset } = useForm<FormValues>({ defaultValues: { description: "" } }); const [fetchedData, setFetchedData] = useState<string>(""); // 模拟异步获取数据 useEffect(() => { const fetchData = async () => { const data = await new Promise<string>(resolve => setTimeout(() => resolve("初始获取的数据"), 1000) ); setFetchedData(data); // 用reset初始化表单值 reset({ description: data }); }; fetchData(); }, [reset]); const onSubmit = (data: FormValues) => { console.log("提交的数据:", data); // 处理提交逻辑 }; return ( <div style={{ padding: 20, maxWidth: 400 }}> <form onSubmit={handleSubmit(onSubmit)}> <CustomTextField control={control} name="description" label="Description" type="text" variant="outlined" fullWidth margin="normal" /> <button type="submit" style={{ marginTop: 20 }}>提交</button> </form> </div> ); }
关键说明
- 表单值完全由React Hook Form管理,避免外部状态与表单状态冲突
reset方法是React Hook Form初始化/更新表单值的标准方式,能确保表单内部状态与显示同步- 增强了类型约束,提升代码可维护性
- 增加了错误状态展示,符合MUI的表单交互规范
内容的提问来源于stack exchange,提问作者Toby
相关产品推荐
相关产品推荐

