Cómo crear un formulario en React (la manera correcta)

Los formularios son de los elementos más usados en el desarrollo de aplicaciones, por lo tanto, es fundamental saber manejarlos de la manera más correcta posible.

En el caso de React, hay muchas formas de crearlos y manejarlos, sin embargo, cada una de las maneras será mejor o peor de acuerdo al caso.

Así que en esta ocasión te traemos 4 formas distintas formas de crear y manejar formularios en React o cualquiera de sus metaframewors (next.js, Gatsby, etc).,

Método #1: Usando useState

La primera opción es utilizar como apoyo el hook “useState()”.

En la documentación de React, esta es la opción más utilizada ya que es la más sencilla de entender, por lo tanto, es la forma favorita de muchos desarrolladores. Sin embargo, ya cuando estamos trabajando en aplicaciones para producción, posiblemente hay mejores opciones (como veremos más adelante).

Acá va un ejemplo de como declarar un formulario de login usando useState().

import {useState} from 'react'

const LoginPageExample = () => {
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')
  
  const handleEmail = (event) => {
    setEmail(event.target.value);
  };

  const handlePassword = (event) => {
    setPassword(event.target.value);
  };

  const handleOnClick = (e) => {
    e.preventDefault()
    //El código para hacer login …
		console.log(email, password)
  }

  return (
    <div>
      <label>Email</label>
      <input type="email" name="email" onChange={handleEmail} />

      <label>Password</label>
      <input type="password" name="password" onChange={handlePassword}/>

      <button type="submit" onClick={handleOnClick}>Login</button>
    </div>
  )
}

export default LoginPageExample

¿Cuándo usar esta manera?

Puede usarse en cualquiera de los casos, sin embargo desde la llegada de los custom hooks y otras librerías de formularios, solo se recomienda cuando se trabajan muy pocos formularios. Por ejemplo, un cuadro de búsqueda.

Ventajas

  • Es la opción más rápida de implementar y entender.
  • Se pueden realizar modificaciones de forma sencilla.

Desventajas

  • Mezcla la lógica del funcionamiento del formulario con la parte visual.
  • SI hay varios inputs, el código se vuelve ilegible.

Método #2: Usando custom hooks (recomendado)

Esta forma es igual que la anterior, pero en vez de tener que declarar toda la lógica del componente y  definir explícitamente los estados, se utiliza un custom hooks.

Ejemplo de formulario para un login.

Declaración del custom hook

import { useState } from "react";

export const useInput = (initialValue: string, type: string) => {
  const [value, setValue] = useState(initialValue);
  const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setValue(e.target.value);
  };
  return { type, value, onChange };
};

Implementación del formulario

import {useState} from 'react'
import {useInput} from './hooks'// Importar el cusotm hook "useImput"

const LoginPageExample = () => {
  const email = useInput('text')  
  const password = useInput('password')  

  const handleSubmit = (e) => {
    e.preventDefault()
    //El código para hacer login …
  }

  return (
    <div>
      <label>Email</label>
      <input {...email} name="email" />

      <label>Password</label>
      <input {password} name="password" />

      <button type="submit">Login</button>
    </div>
  )
}

¿Cuándo usar esta forma?

Por sus características, el uso de custom hooks como useInput es ideal en formularios donde se requiere manejar de forma completa el estado de los input, como por ejemplo, en formularios de edición.

Asimismo, esta opción es ampliamente utilizada en la documentación de React, por lo que puede considerarse que está entre las «buenas prácticas» de la librería.

Ventajas

  • Aumentan la legibilidad y la reutilización del código (mantenibilidad)
  • Agrupa toda la lógica en un solo lugar.

Desventajas

  • Si hay muchos inputs, el código se vuelve poco legible.
  • En algunos casos puede ser muy restrictivo manejar custom hooks, por lo que dependiendo de la situación puede no llegar a funcionar.

Método #3: Manejar todo en un solo estado (recomendado)

Otra de las alternativas más populares para manejar formularios es agrupar todos los componentes en un solo estado.

Esta aproximación suele considerarse como la más limpia de todas, ya que utiliza atributos y elementos propios del DOM para funcionar. Asimismo, en vez de crear estados para cada uno de los inputs, todo se agrupa en un objeto de JavaScript.

Ejemplo:

const LoginPageExampleB = () => {

  const handleSubmit = (e) => {
    e.preventDefault()
		const data = {
			email: e.target.email.value,
			password: e.target.password.value
		}
        //El código para hacer login …
		console.log(data.email, data.password)
  }

  return (
    <form onSubmit={handleSubmit}>
      <label>Email</label>
      <input type="email" name="email" />

      <label>Password</label>
      <input type="password" name="password" />

      <button type="submit">Login</button>
    </form>
  )
}

export default LoginPageExampleB

¿Cuando usarse?

Esta es la opción ideal cuando se necesita trabajar propiamente con formularios de creación, es decir, componentes que registraran algún elemento a la base de datos.

Ventajas

  • La lógica se agrupa en un solo estado, por lo que no es necesario crear más estados por cada componente.
  • Es más sencillo realizar validaciones.

Desventajas

  • Incrementa la lógica dentro del componente.
  • No se pueden usar estados ya definidos.
  • Es necesario utilizar un componente de tipo «form».

Método #4: Usar librerías (recomendado)

Por último, están las librerías de formularios.

Este tipo de complementos te permiten no solo manejar los estados de los formularios, sino también realizar tareas adicionales como la validación de tipos, restricciones de valores, etc.

Entre las opciones más comunes tenemos:

  • Formik (la opción más popular de todas)
  • React Final Form
  • react-form

Ventajas

  • Permiten realizar validaciones de manera rápida y adecuada.
  • Incrementan la seguridad y robustes de los formularios

Desventajas

  • Aumentan el número de dependencias en el proyecto, por lo que puede aumentar el peso de la aplicación
  • Aportan poco en el caso de formularios sencillos.

No uses “useRef”

Otro de los métodos más populares para manejar formularios es usar useRef para manejar los estados.

Si bien, el uso de referencias en teoría debería ser la «opción correcta» para el manejo de formularios ya que no permite rerenderizar la aplicación cuando cambia el estado del componente, lo cierto es que el mismo equipo de React dejó de recomendar esta opción, debido a que lo considera que puede implicar un “sobre uso de referencias”.

Conclusión: ¿cuál elegir?

Cada uno de los métodos mencionado, irá de mejor manera según el caso que esté implementado. Por ejemplo:

  • Los formularios con custom hooks (2do método) mejoran la mantenibilidad del proyecto, ya que separan por completo la lógica con la vista. Aunque en formularios con muchos inputs puede incrementar la cantidad de código.
  • Mientras tanto, el agrupar todos los formularios en un estado (método 3) ayuda a que el código sea más limpio y permite realizar validaciones de forma sencilla.
  • En el caso de proyectos más grandes, el uso de librerías como Formik suelen ser las opciones ideales, ya que otorgan funcionalidad probadas y desarrolladas siguiendo buenas prácticas de desarrollo y patrones de arquitectura.

TaggedFormularios