所以我一直在尝试使用react-hook-form创建一个多步骤表单,我成功地做到了这一点,作为创造价值的一种方式。
但是当涉及到更新它们时。有点难。它确实有效,因为它确实获取数据来填充表单。它确实成功更新了我的数据库上的表。但它似乎没有为输入提供默认值。
我尝试使用 useForm() Hook 的 defaultValues{} 选项,但由于它的值是从后端获取的,因此需要重置。
然而,当我实施它们时......什么也没有发生。数据就在那里,我已经测试过了。它确实会重置,但在 .tsx 文件中......什么也没有。
即使我 console.log(watch()) 也只出现空字符串或空值。我尝试过强制将值作为道具,但它看起来很糟糕,我不认为这是处理它的方法。特别是因为存在 defaultValues 选项。
也许错误是因为我使用的是多步骤表单,但我不明白为什么它不起作用。
我仍在努力学习 React。因此,我们非常感谢任何有关如何解决此问题以及代码本身的反馈或指导。
这些是相关的代码片段:
//EditarDentista.tsx:这是保存 apiQueries 并处理大部分逻辑的主页:
const EditarDentista = () => {
const { idDentista } = useParams();
const { data: dentista, isLoading: fetching } = useQuery(
["fetchDentista", idDentista], // Include idDentista in the query key
() => apiClient.getSingleDentista(idDentista as string),
{ retry: 0 }
);
const { mutate, isLoading } = useMutation(
({ idDentista, data }: { idDentista: string; data: EditarDentistaFormType }) =>
apiClient.updateDentista(idDentista, data),
{
onSuccess: () => {
alert("Success");
},
onError: () => {
alert("Error:");
},
}
);
const onSave = (data: EditarDentistaFormType) => {
if (idDentista) {
mutate({ idDentista, data });
} else {
<Navigate to={'/'} />; // TODO: Improve Error Handler
}
};
return (
<ManageEditarDentista isEditing={isLoading} onSave={onSave} dentista={dentista} isFetching={fetching} />
);
};
//将保存状态的管理器、formProvider 以及使用 fetchedValues
const ManageEditarDentista = ({ onSave, isEditing, dentista, isFetching }: ManageEditarDentistaProps) => {
const formMethods = useForm<EditarDentistaFormType>();
const { reset, handleSubmit } = formMethods;
const [paginaActual, setPaginaActual] = useState(0);
console.log(dentista, 1);
useEffect(() => {
if (dentista) {
reset({
nombre: dentista.nombre,
apPaterno: dentista.apPaterno,
apMaterno: dentista.apMaterno,
correo: dentista.correo,
carnet: dentista.carnet,
fechaNacimiento: dentista.fechaNacimiento,
telefono: dentista.telefono,
especialidad: dentista.especialidad
});
}
}, [dentista, reset]);
console.log(dentista, 2);
if (isFetching) {
return (
<div className="w-full h-screen flex items-center justify-center">
<TailSpin
visible={true}
height="100%"
width="100%"
color="#D10056"
ariaLabel="tail-spin-loading"
radius="1"
wrapperStyle={{}}
wrapperClass=""
/>
</div>
);
}
const onSubmit = handleSubmit((data: EditarDentistaFormType) => {
if (paginaActual !== 1) {
setPaginaActual(prev => prev + 1);
} else {
onSave(data);
}
});
return (
<div className="w-full h-full flex items-center justify-center">
<FormProvider {...formMethods}>
<form className="w-[60vw] h-[60vh] bg-slate-400" onSubmit={onSubmit}>
{paginaActual === 0 && <Pagina1FormularioEditar />}
{paginaActual === 1 && <Pagina2FormularioEditarDentista />}
{paginaActual == 1 && <button onClick={() => setPaginaActual(paginaActual - 1)}>Back</button>}
<button
disabled={isEditing}
className="py-1 px-2 disabled:bg-slate-800 bg-slate-500 hover:bg-slate-300"
type="submit"
>
{isEditing ? "Loading..." : paginaActual === 1 ? "Submit" : "Next"}
</button>
</form>
</FormProvider>
</div>
);
}
//以其中一页为例:
const { register, formState: { errors }, watch } = useFormContext<EditarDentistaFormType>()
console.log(watch());
return (
<div className="flex flex-col gap-4">
<div className=" bg-slate-500 flex justify-center items-center h-5">
Informacion Personal:
</div>
<label className="text-gray-700 text-sm font-bold flex-1 mx-10 ">
Nombre:
<input type="text"
className="border border-blue-500 w-full py-1 px-2 font-normal"
{...register("nombre", { required: "This field is required" })} />
</label>
<label>
Apellido Paterno:
<input type="text" {...register("apPaterno", { required: "This field is required" })} />
{errors.apPaterno && <span className="text-sm text-red-500 font-semibold">{errors.apPaterno.message}</span>}
</label>
<label>
Apellido Materno:
<input type="text" {...register("apMaterno", { required: "This field is required" })} />
{errors.apMaterno && <span className="text-sm text-red-500 font-semibold">{errors.apMaterno.message}</span>}
</label>
<label>
Carnet:
<input type="text"
{...register("carnet", { required: "This field is required" })} />
{errors.carnet && <span className="text-sm text-red-500 font-semibold">{errors.carnet.message}</span>}
</label>
</div>
)
}
它是功能代码......我认为......因为它确实更新。但如果没有实际看到当前的数据更新就真的很麻烦了。
无论如何,我感谢您花时间阅读我的臭代码,正如我所说,非常欢迎任何反馈或指导。谢谢您的宝贵时间!
尝试
values
的
useForm
道具
values 属性将对更改做出反应并更新表单值,这在您的表单需要通过外部状态或服务器数据更新时非常有用。 -反应钩子形式
https://react-hook-form.com/docs/useform#defaultValues
// set default value sync
function App({ values }) {
useForm({
values, // will get updated when values props updates
})
}
function App() {
const values = useFetch("/api")
useForm({
defaultValues: {
firstName: "",
lastName: "",
},
values, // will get updated once values returns
})
}