Manejo simple de formularios con React JS

Junio 27, 2021

El manejo de formularios es una actividad muy común al momento de desarrollar páginas web, actualmente existe numerosas librerías para react que te ayudan al desarrollo y control de los formularios, como por ejemplo Formik, pero en ocasiones utilizar una librería de terceros a veces resulta demasiado cuando solo intentamos desarrollar formularios sencillos.

En esta ocasión te mostraré una forma sencilla de cómo trabajar con formularios en React JS creando un custom hook sencillo.

Primero vamos a crear un nuevo proyecto con el viejo confiable npx create-react-app, utilice la consola de su preferencia y ejecute npx create-react-app formulario-sencillo.

Una vez creado el proyecto, reemplazaremos el contenido de App.js con el siguiente código:

function App() {
  return (
    <div style={{ padding: "20px" }}>
      <h2>Formulario con REACT</h2>
      <form>
        <label htmlFor="nombre">Nombre</label>
        <br />
        <input type="text" name="nombre" />
        <br />
        <label htmlFor="apellido">Apellido</label>
        <br />
        <input type="text" name="apellido" />
        <br />
        <label htmlFor="edad">Edad</label>
        <br />
        <input type="number" name="edad" />
        <br />
        <span>Genero</span>
        <br />
        <label>
          <input type="radio"
            name="genero"
            value="F" />
          Femenino</label>
        <label>
          <input type="radio"
            name="genero"
            value="M" />
          Masculino</label>
        <br />
        <label>Lenguaje de programación favorito</label>
        <br />
        <select>
          <option>Seleccione una opción</option>
          <option>C#</option>
          <option>Java</option>
          <option>C++</option>
          <option>Python</option>
          <option>Otro</option>
        </select>
        <br />
        <label>
          <input type="checkbox" name="terminos" />
          He leido los terminos y condiciones</label>
          <br/>
          <button type="button">Limpiar</button>
          <button type="button">Resetear</button>
      </form>
    </div>
  );
}

export default App;

Al cagar el sitio se debe mostrar un formlario como este:

Formulario

Creación de un custom hook para controlar el formulario

Ahora vamos a crear un custom hook llamado useForm, para organizar el proyecto, crearé una carpeta llamada utility y dentro de ella crearemos el archivo useForm.js que será nuestro custom hook.

Directorio Custom Hook

Abriremos el archivo useForm.js y colocaremos el siguiente código:

import { useState } from "react";

export default function useForm(initial = {}) {
    const [inputs, setInputs] = useState(initial);

    function handleChange(e) {
        let { name, type, value, checked } = e.target;

        if (type === "checkbox") value = checked;

        if (type === "number") value = parseInt(value);

        setInputs(prev => ({
            ...prev,
            [name]: value
        }));
    }   

    return {
        inputs,
        handleChange
    }
}

El custom hook tendrá initial como parámetro de entrada, este será el valor con el que se inicializará el state de inputs, además cuenta con la función handleChange que se encargará de evaluar el tipo de dato que se está modificando y ajustará la información para poder actualizar el input state.

Uso del custom Hook

Abriremos App.js y modificaremos el código de la siguiente manera:

import useForm from "./utility/useForm";

function App() {
  const { inputs, handleChange } = useForm({
    nombre: "John",
    apellido: "Doe",
    edad: 45,
    terminos: false,
    genero: "F",
    lenguajeProgramacion: ""
  });

  return (
    <div style={{ padding: "20px" }}>
      <h2>Formulario con REACT</h2>
      <form>
        <label htmlFor="nombre">Nombre</label>
        <br />
        <input type="text"
          name="nombre"
          value={inputs.nombre}
          onChange={handleChange} />
        <br />
        <label htmlFor="apellido">Apellido</label>
        <br />
        <input type="text"
          name="apellido"
          value={inputs.apellido}
          onChange={handleChange} />
        <br />
        <label htmlFor="edad">Edad</label>
        <br />
        <input type="number"
          name="edad"
          value={inputs.edad}
          onChange={handleChange} />
        <br />
        <span>Genero</span>
        <br />
        <label>
          <input type="radio"
            name="genero"
            value="F"
            checked={inputs.genero === "F"}
            onChange={handleChange} />
          Femenino</label>
        <label>
          <input type="radio"
            name="genero"
            value="M"
            checked={inputs.genero === "M"}
            onChange={handleChange} />
          Masculino</label>
        <br />
        <label>Lenguaje de programación favorito</label>
        <br />
        <select name="lenguajeProgramacion"
          value={inputs.lenguajeProgramacion}
          onChange={handleChange}>
          <option value="">Seleccione una opción</option>
          <option value="C#">C#</option>
          <option value="Java">Java</option>
          <option value="C++">C++</option>
          <option value="Python">Python</option>
          <option value="Otro">Otro</option>
        </select>
        <br />
        <label>
         <input type="checkbox"
            name="terminos"
            checked={inputs.terminos}
            onChange={handleChange} />
          He leido los terminos y condiciones</label>
        <br />
        <button type="button">Limpiar</button>
        <button type="button">Resetear</button>
      </form>
    </div>
  );
}

export default App;

Para efectos ilustrativos he utilizado el custom hook useForm con datos iniciales, si cargamos nuevamente el sition, se debe poder visualizar el formulario con los datos iniciales, igualmente el formulario se encuentra funcional y podemos realizar cambios sin ningún problema 👌.

Formulario inicializado con custom hook

Limpiar el formulario

Una funcionalidad muy común es limpiar los datos del formulario cuando por ejemplo enviamos los datos del formulario, aquí te mostraré una manera sencilla cómo agregar esta funcionalidad en el custom hook.

Abriremos el archivo useForm.js y modificaremos el código para agregar la función clearForm de la siguiente manera:

import { useState } from "react";

export default function useForm(initial = {}) {
    const [inputs, setInputs] = useState(initial);

    function handleChange(e) {
        let { name, type, value, checked } = e.target;

        if (type === "checkbox") value = checked;
        
        if (type === "number") value = parseInt(value);

        setInputs(prev => ({
            ...prev,
            [name]: value
        }));
    } 
    
    function clearForm() {
        //Convertimos los inputs (json) a un arreglo de arreglos 
        const inputsArray = Object.entries(inputs);

        // Recorremos el arreglo y retornamos un nuevo arreglo de arreglos conservando el key
        const clearInputsArray = inputsArray.map(([key]) => [key, '']);

        //Convertimos el arreglo de arreglos nuevamente a formato json
        const inputsJson = Object.fromEntries(clearInputsArray);

        setInputs(inputsJson);
    }

    return {
        inputs,
        handleChange,
        clearForm
    }
}

Abriremos el archivo App.js y lo modificaremos para incorporar la funcionalidad de limpiar el form en el onClick del botón Limpiar.

import useForm from "./utility/useForm";

function App() {
  const { inputs, handleChange, clearForm } = useForm({
    nombre: "John",
    apellido: "Doe",
    edad: 45,
    terminos: false,
    genero: "F",
    lenguajeProgramacion: ""
  });

  return (
    <div style={{ padding: "20px" }}>
      <h2>Formulario con REACT</h2>
      <form>
        <label htmlFor="nombre">Nombre</label>
        <br />
        <input type="text"
          name="nombre"
          value={inputs.nombre}
          onChange={handleChange} />
        <br />
        <label htmlFor="apellido">Apellido</label>
        <br />
        <input type="text"
          name="apellido"
          value={inputs.apellido}
          onChange={handleChange} />
        <br />
        <label htmlFor="edad">Edad</label>
        <br />
        <input type="number"
          name="edad"
          value={inputs.edad}
          onChange={handleChange} />
        <br />
        <span>Genero</span>
        <br />
        <label>
          <input type="radio"
            name="genero"
            value="F"
            checked={inputs.genero === "F"}
            onChange={handleChange} />
          Femenino</label>
        <label>
          <input type="radio"
            name="genero"
            value="M"
            checked={inputs.genero === "M"}
            onChange={handleChange} />
          Masculino</label>
        <br />
        <label>Lenguaje de programación favorito</label>
        <br />
        <select name="lenguajeProgramacion"
          value={inputs.lenguajeProgramacion}
          onChange={handleChange}>
          <option value="">Seleccione una opción</option>
          <option value="C#">C#</option>
          <option value="Java">Java</option>
          <option value="C++">C++</option>
          <option value="Python">Python</option>
          <option value="Otro">Otro</option>
        </select>
        <br />
        <label>
          <input type="checkbox"
            name="terminos"
            checked={inputs.terminos}
            onChange={handleChange} />
          He leido los terminos y condiciones</label>
        <br />
        <button type="button" onClick={clearForm}>Limpiar</button>
        <button type="button">Resetear</button>
      </form>
    </div>
  );
}

export default App;

Ahora si llenamos el formulario y presionamos el botón de limpiar veremos que todos los campos se limpiarán 😁.

Resetear el formulario a sus valores originales

Otra funcionalidad muy común es la de resetear el formulario a sus valores iniciales, veamos cómo aplicar esta funcionalidad en nuestro custom hook.

Modificaremos nuevamente el arhivo useForm.js para agregar la nueva función resetForm de la siguiente manera:

import { useState } from "react";

export default function useForm(initial = {}) {
    const [inputs, setInputs] = useState(initial);

    function handleChange(e) {
        let { name, type, value, checked } = e.target;

        if (type === "checkbox") value = checked;
        
        if (type === "number") value = parseInt(value);

        setInputs(prev => ({
            ...prev,
            [name]: value
        }));
    } 
    
    function clearForm() {
        //Convertimos los inputs (json) a un arreglo de arreglos 
        const inputsArray = Object.entries(inputs);

        // Recorremos el arreglo y retornamos un nuevo arreglo de arreglos conservando el key
        const clearInputsArray = inputsArray.map(([key]) => [key, '']);

        //Convertimos el arreglo de arreglos nuevamente a formato json
        const inputsJson = Object.fromEntries(clearInputsArray);

        setInputs(inputsJson);
    }

    function resetForm() {
        setInputs(initial);
    }

    return {
        inputs,
        handleChange,
        clearForm
    }
}

Ahora modificaremos el archivo App.js para incorporar la función de resetear el form y los anclaremos al onClick del botón Resetear.

import useForm from "./utility/useForm";

function App() {
  const { inputs, handleChange, clearForm, resetForm } = useForm({
    nombre: "John",
    apellido: "Doe",
    edad: 45,
    terminos: true,
    genero: "F",
    lenguajeProgramacion: "C#"
  });

  return (
    <div style={{ padding: "20px" }}>
      <h2>Formulario con REACT</h2>
      <form>
        <label htmlFor="nombre">Nombre</label>
        <br />
        <input type="text"
          name="nombre"
          value={inputs.nombre}
          onChange={handleChange} />
        <br />
        <label htmlFor="apellido">Apellido</label>
        <br />
        <input type="text"
          name="apellido"
          value={inputs.apellido}
          onChange={handleChange} />
        <br />
        <label htmlFor="edad">Edad</label>
        <br />
        <input type="number"
          name="edad"
          value={inputs.edad}
          onChange={handleChange} />
        <br />
        <span>Genero</span>
        <br />
        <label>
          <input type="radio"
            name="genero"
            value="F"
            checked={inputs.genero === "F"}
            onChange={handleChange} />
          Femenino</label>
        <label>
          <input type="radio"
            name="genero"
            value="M"
            checked={inputs.genero === "M"}
            onChange={handleChange} />
          Masculino</label>
        <br />
        <label>Lenguaje de programación favorito</label>
        <br />
        <select name="lenguajeProgramacion"
          value={inputs.lenguajeProgramacion}
          onChange={handleChange}>
          <option value="">Seleccione una opción</option>
          <option value="C#">C#</option>
          <option value="Java">Java</option>
          <option value="C++">C++</option>
          <option value="Python">Python</option>
          <option value="Otro">Otro</option>
        </select>
        <br />
        <label>
          <input type="checkbox"
            name="terminos"
            checked={inputs.terminos}
            onChange={handleChange} />
          He leido los terminos y condiciones</label>
        <br />
        <button type="button" onClick={clearForm}>Limpiar</button>
        <button type="button" onClick={resetForm}>Resetear</button>
      </form>
    </div>
  );
}

export default App;

Ahora, si modificamos los datos del formulario o limpiamos el formulario, si hacemos click en el botón Resetear, notaremos que el formulario volverá a cargar los datos con los que inicializamos el custom hook.

Ahora ya tienes un custom hook que puedes reutilizar en distintos formularios para tus próximos proyectos con React JS.


Profile picture

Blog personal de Marcos Zhu, en este espacio comparto lo que aprendo porque enseñando es la mejor forma de aprender.