Quiero proporcionar valores predeterminados en el campo de entrada usando react-hook-form
. Primero recupero los datos del usuario del punto final de la API y luego configuro los users
de estado para esos datos de usuario. Luego paso los users
del estado a los valores predeterminados de defaultValues
useForm()
.
import React, { useState, useEffect } from "react"; import { useForm } from "react-hook-form"; import axios from "axios"; function LoginFile() { const [users, setUsers] = useState(null); useEffect(() => { axios .get("http://localhost:4000/users/1") .then((res) => setUsers(res.data)); }, []); useEffect(() => { console.log(users); }, [users]); const { register, handleSubmit, errors } = useForm({ defaultValues: users, }); return ( <div> <form onSubmit={handleSubmit(onSubmit)}> Email <input type="email" name="email" ref={register} /><br /> firstname <input name="firstname" ref={register} /><br/> <input type="submit" /> </form> </div> ); } export default LoginFile;
Lo hice con el código anterior pero no funcionó como se esperaba. Todos los campos de entrada todavía están vacíos. Quiero tener algunos valores predeterminados en el campo de entrada de mi formulario.
Eso definitivamente funcionó. Usando la API de reinicio y el UseEffect.
Comenzando con picaduras vacías como valores predeterminados y actualizándolas como efectos con el reinicio. Aquí está mi código. Estaba usando TypeScript con Ionic aquí también...
const { control: editControl, handleSubmit: editSubmit, reset } = useForm<EditFormType>({ defaultValues: { question: "", optionA: "", optionB: "", optionC: "", optionD: "", } }); useEffect(() => { let defaults ={ question: editQuestion?.body, optionA: editQuestion?.options[0].body, optionB: editQuestion?.options[1].body, optionC: editQuestion?.options[2].body, optionD: editQuestion?.options[3].body, } reset(defaults) }, [editQuestion, reset])
El problema es que durante el primer renderizado, users
tienen el valor inicial del gancho useState
, que es null
. El valor solo cambia después de que finaliza la solicitud axios.get()
, que es después del renderizado inicial. Esto significa que los valores predeterminados pasados a useForm
son null
.
La documentación de defaultValues dice lo siguiente:
Los
defaultValues
se almacenan en caché en el primer renderizado dentro del gancho personalizado. Si desea restablecer losdefaultValues
, debe usar la API dereset
.
Por lo tanto, solo necesitará usar reset
para restablecer el formulario manualmente a los valores que obtiene. La documentación para reset
dice lo siguiente:
Deberá pasar
useForm
defaultValues
reset
el valor de los componentes delController
.
Sin embargo, no está claro en la documentación si null
es suficiente como valores predeterminados o si necesita pasarle un objeto adecuado con campos para cada entrada. Para ir a lo seguro, supongamos que es lo último.
El código para hacer esto sería algo como esto:
function LoginFile() { const [users, setUsers] = useState({ email: "", firstname: "" }); const { register, handleSubmit, errors, reset } = useForm({ defaultValues: users, }); useEffect(() => { axios.get("http://localhost:4000/users/1").then((res) => { setUsers(res.data); reset(res.data); }); }, [reset]); useEffect(() => { console.log(users); }, [users]); return ( <div> <form onSubmit={handleSubmit(onSubmit)}> Email <input type="email" name="email" ref={register} /> <br /> firstname <input name="firstname" ref={register} /> <br /> <input type="submit" /> </form> </div> ); }
Además, si la única razón para el enlace useState es almacenar el valor de defaultValues
, no lo necesita en absoluto y puede limpiar el código para que sea:
function LoginFile() { const { register, handleSubmit, errors, reset } = useForm({ defaultValues: { email: "", firstname: "" }, }); useEffect(() => { axios.get("http://localhost:4000/users/1").then((res) => { reset(res.data); }); }, [reset]); return ( <div> <form onSubmit={handleSubmit(onSubmit)}> Email <input type="email" name="email" ref={register} /> <br /> firstname <input name="firstname" ref={register} /> <br /> <input type="submit" /> </form> </div> ); }