¿Alguna vez has necesitado validar y administrar cada campo de datos en formularios con React ?
Imagine la situación: está navegando por un proyecto y se enfrenta con desafío de mantener los formularios organizados y sin errores. Los formularios son complejos con muchos campos y su código puede resultar confuso y difícil de mantener.
¿Algo de eso te parece familiar?
Aquí es donde entra en juego React Hook Form . Esta biblioteca se encarga de todo el proceso de validación de formularios, permitiéndole crear formularios eficientes con menos código.
Es muy flexible, con validaciones basadas en restricciones que aprovechan el marcado HTML existente.
Es súper liviano y minimiza la cantidad de renderizaciones de páginas, lo que mejora el rendimiento de la página.
Entonces, en este artículo exploraremos cómo React Hook Form administra y valida los campos de nuestro formulario.
Aprenderás:
Y mucho más. ¡Abróchate el cinturón y vámonos!
Antes de trabajar con React Hook Form, es fundamental comprender la diferencia entre componentes controlados y no controlados, ya que la biblioteca tiene diferentes formas de tratar ambos tipos. Así que entendamos mejor a cada uno.
En un componente no controlado , el estado lo mantiene el propio DOM, y no React.
Esto significa que en un formulario, React no conoce el estado de la entrada a menos que obtenga esa información utilizando otros recursos, por ejemplo useRef()
.
import React, { useRef } from 'react';
function Formulario() {
const nombreRef = useRef();
const emailRef = useRef();
const handleSubmit = (e) => {
e.preventDefault();
// Accesando a los valores de los inputs diretamente por los elementos del formulário
console.log(nombreRef.current.value);
console.log(emailRef.current.value);
};
return (
<form onSubmit={handleSubmit}>
<input
ref={nombreRef}
name="nombre"
type="text"
/>
<input
ref={emailRef}
name="email"
type="email"
/>
<button type="submit">Enviar</button>
</form>
);
}
Este enfoque se acerca más a la forma en que normalmente funciona HTML, es decir, los valores de estos componentes se definen y se leen a través de atributos HTML, como value
, checked
(para checkboxes), selected
(para select), etc.
import './App.css'
function App() {
const onFormSubmit = (event) => {
event.preventDefault()
const form = event.target;
const inputs = form.elements;
const values = {};
for (let i = 0; i < inputs.length; i++) {
const input = inputs[i];
if (input.name) {
values[input.name] = input.value;
}
}
console.log(values);
}
return (
<>
<form onSubmit={onFormSubmit}>
<input type="text" name='nombre' placeholder='tu nombre'/>
<input type="email" name='email' placeholder='tu email'/>
<button type="submit">
enviar
</button>
</form>
</>
)
}
export default App
Los componentes controlados tienen su estado totalmente controlado por React.
Esto significa que los valores de los campos se almacenan como parte del estado del componente.
Los valores de los campos del formulario se actualizan en respuesta a los cambios de estado de React. Imagino que alguna vez ya viste un componente controlado como este:
import React, { useState } from "react";
export const Form = () => {
const [input, setInputValues] = useState({name: "", email:""});
const handleChange = (e) => {
const { name, value } = e.target;
setInputValues({ ...inputValues, [name]: value });
};
function onSubmit(event) {
event.preventDefault();
console.log(input)
}
return (
<form onSubmit={onSubmit}>
<label>
Name:
<input
type="text"
onChange={(e) => handleChange(e)}
value={input.name}
/>
</label>
<label>
Email:
<input
type="email"
onChange={(e) => handleChange(e)}
value={input.email}
/>
</label>
<button type="submit">Enviar</button>
</form>
);
};
Los componentes controlados le brindan más control sobre los datos del formulario y son los más recomendados cuando se trabaja con formularios.
Si quieres ver ejemplos de componentes controlados en React, incluyendo checkboxes , select , radio botones y mucho más, te recomiendo leer el artículo de Jorge Nascimento sobre la plataforma Dev.to .
Sin embargo, ya sea que utilice componentes controlados o no controlados, sus formularios pueden resultar difíciles de mantener.
En momentos como este vale la pena conocer una forma de gestionarlos. Y ahí es donde entra en juego React Hook Form.
Esta biblioteca se encarga de todo el proceso de validación de formularios, permitiéndo crear formularios eficientes, flexibles y de alto rendimiento, ya que elimina la representación innecesaria.
React Hook Form utiliza un enfoque de manos libres para administrar el estado de los campos del formulario, lo que significa menos código y mejor rendimiento.
Así, por ejemplo:
import React from 'react';
import { useForm } from 'react-hook-form';
function Form() {
const { register, handleSubmit } = useForm();
const onSubmit = data => {
console.log(data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register("name")} placeholder="Nombre" />
<input {...register("email")} placeholder="Email" />
<button type="submit">Enviar</button>
</form>
);
}
Con React Hook Form, registra los campos de su formulario usando la función register
, que esencialmente asocia un campo de entrada HTML con el estado interno de la biblioteca.
Esto permite que React Hook Form administre el estado del formulario, sin la necesidad de crear estados separados para cada campo.
Si desea comprender cómo register
funciona, las funciones que devuelve y los props que acepta, le recomiendo leer la documentación del formulario React Hook haciendo clic en este enlace .
En el ejemplo anterior, usamos register
para asociar los campos de entrada del formulario con el estado interno del formulario React Hook.
Esto nos permite acceder a los valores de los campos en el momento que se envía el formulario.
Quizás te preguntes: "¿Cómo?"
La magia está en el register
. Cuando hacemos:
<input {...register("nombre")} placeholder="Nombre" />
Es lo mismo que hacerlo de esta forma:
const { onChange, onBlur, name, ref } = register('nome');
<input
onChange={onChange}
onBlur={onBlur}
name={name}
ref={ref}
placeholder="Nome"
/>
El register
devuelve algunas funciones importantes. El ref
nos permite obtener los valores de este campo, y mediante la lógica interna podemos actualizar este valor con el onChange
a través del formulario React Hook.
En algunas situaciones, es posible que su aplicación ya tenga componentes desarrollados por ti (inputs, selects / dropdown, radio button, checkbox…
) siguiendo los estándares de design de su equipo.
En casos como este, tiene más sentido integrarse con la biblioteca React Hook Form que desarrollar nuevos componentes desde cero. Veamos cómo implementar esto, usando el siguiente componente como ejemplo <Select>
:
import { forwardRef } from 'react'
export interface IFormValues {
name: string;
age: number;
}
const Select = forwardRef<
HTMLSelectElement,
{ label: string } & ReturnType<UseFormRegister<IFormValues>>
>(({ label }, ref) => (
<div>
<label>{label}</label>
<select ref={ref} >
<option value="20">20</option>
<option value="30">30</option>
</select>
</div>
)
);
En el componente Select
, usamos forwardRef()
para pasar ref
directamente al select
HTML.
Esto nos permite integrar fácilmente el componente con React Hook Form manteniendo la referencia al campo de edad ( age
).
De forma predeterminada, los nodos del DOM de un componente son privados. Sin embargo, a veces es útil exponer un nodo del DOM a su componente principal, por ejemplo, para permitir que se pueda enfocar o, en este caso, para tener acceso a atributos como value
, onchange
, name
, etc.
forwardRef
permite que su componente exponga un nodo del DOM al componente principal con una referencia.
Si desea obtener más información sobre forwardRef
y sus usos, te recomiendo leer la documentación de React haciendo clic en este enlace aquí .
También puedes usar register
directamente dentro de tu componente, siempre que lo aceptes como prop.
Ten en cuenta que la propia biblioteca React Hook Form nos proporciona tipos para evitar escribir incorrectamente los props de nuestros componentes personalizados.
import { Path, UseFormRegister } from "react-hook-form"
import { IFormValues } from './'
type InputProps = {
label: Path<IFormValues>
register: UseFormRegister<IFormValues>
required: boolean
}
const Input = ({ label, register, required }: InputProps) => (
<>
<label>{label}</label>
<input {...register(label, { required })} />
</>
)
En el ejemplo anterior, el componente <Input />
recibe props label
, register
y un required
. El register se devuelve desde la biblioteca React Hook Form, mientras que lo requerido es un objeto que contiene las reglas de validación que el register puede recibir.
Podría utilizar estos componentes de la siguiente manera:
import { useForm, SubmitHandler } from "react-hook-form"
import { Input, Select } from './'
import IFormValues from './'
const App = () => {
const { register, handleSubmit } = useForm<IFormValues>()
const onSubmit: SubmitHandler<IFormValues> = (data) => {
alert(JSON.stringify(data))
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Input label="name" register={register} required />
<Select label="age" {...register("age")} />
<input type="submit" />
</form>
)
}
Quizás se pregunte: "¿Pero qué pasa con los casos en los que utilizamos componentes de interfaz de usuario de bibliotecas de terceros para crear la interfaz de nuestra aplicación?"
¡Es una excelente pregunta! Entendamos cómo trabajamos con este tipo de componentes.
Cuando utilizamos bibliotecas de componentes como MUI y Ant Design , podemos integrar React Hook Form sin ningún problema, incluso cuando estos componentes no aceptan directamente una referencia.
En este tipo de escenario, React Hook Form se encarga de todo el proceso de registro de nuestros componentes:
import { useForm, Controller, SubmitHandler } from "react-hook-form"
import { Input } from "@material-ui/core"
interface IFormInput {
nombre: string
contraseña: string
}
const App = () => {
const { control, handleSubmit } = useForm<IFormInput>({
defaultValues: {
nombre: "",
contraseña: ""
},
})
const onSubmit: SubmitHandler<IFormInput> = (data) => {
console.log(data)
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Controller
name="nombre"
control={control}
render={({ field }) => <Input {...field} />}
/>
<Controller
name="contraseña"
control={control}
render={({ field }) => <Input {...field} />}
/>
<button type="submit">Enviar</button>
</form>
)
}
Dentro del formulario tenemos dos componentes Controller
, uno para cada campo (nombre y contraseña).
Controller
se utiliza para integrar campos de entrada de bibliotecas externas en react-hook-form
.
Este componente recibe algunos props, incluyendo un name que sirve como identificador único para el campo, un render , que representa el componente externo que estamos usando y un control , que será responsable de controlar el componente externo.
Y así es como podemos integrar la biblioteca React Hook Form con componentes de bibliotecas de UI externas.
El componente Controller
puede recibir otros accesorios, y si quieres profundizar en su uso te recomiendo leer la documentación disponible aquí en este enlace .
React Hook Form es una herramienta poderosa para simplificar la validación de formularios en React.
Al adoptar un enfoque no controlado y admitir componentes controlados a través del Controller , la herramienta le permite crear formularios eficientes con menos código y mejor rendimiento.
Si desea profundizar su conocimiento en React, le sugiero que realice nuestra capacitación de React .
Y hay cursos especifícos donde aprenderas más sobre hooks en React . Y nuestro Alura+ dónde aprenderás ¿qué son, y cómo funcionan?.
Espero verte allí! ¡Hasta la próxima!
Artículo adaptado y traducido por Daysibel Cotiz.
Neilton Seguins
Me gradué con una licenciatura en Ciencia y Tecnología e Ingeniería Mecánica. Trabajo como Instructor de desarrollo de software en Alura y tengo experiencia en desarrollo usando JavaScript/TypeScript, React js, Next js y Node.js. Me encanta compartir conocimientos, porque creo que la educación es transformadora y quiero cambiar la vida de las personas a través de la educación así como yo logré cambiar mi vida. También me encanta escuchar y tocar música, leer libros y manga y ver series.
Cursos de Programación, Front End, Data Science, Innovación y Gestión.
Luri es nuestra inteligencia artificial que resuelve dudas, da ejemplos prácticos y ayuda a profundizar aún más durante las clases. Puedes conversar con Luri hasta 100 mensajes por semana
Paga en moneda local en los siguientes países
Cursos de Programación, Front End, Data Science, Innovación y Gestión.
Luri es nuestra inteligencia artificial que resuelve dudas, da ejemplos prácticos y ayuda a profundizar aún más durante las clases. Puedes conversar con Luri hasta 100 mensajes por semana
Paga en moneda local en los siguientes países
Puedes realizar el pago de tus planes en moneda local en los siguientes países:
País | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
Plan Semestral |
486.67
BOB |
69704.84
CLP |
290438.59
COP |
65.90
USD |
259.47
PEN |
1441.54
MXN |
3031.66
UYU |
65.90
USD |
533.19
GTQ |
34952.61
CRC |
4234.92
DOP |
Plan Anual |
737.76
BOB |
105667.89
CLP |
440285.52
COP |
99.90
USD |
393.34
PEN |
2185.29
MXN |
4595.79
UYU |
99.90
USD |
808.29
GTQ |
52985.83
CRC |
6419.86
DOP |
Acceso a todos
los cursos
Estudia las 24 horas,
dónde y cuándo quieras
Nuevos cursos
cada semana