# React Hooks Formularios

En esta sección aprenderemos a trabajar con formularios en React, utilizando Hooks.

¿Quieres apoyar los directos? 😍

Tienes varias jugosas alternativas:

  1. Suscríbete al canal de Youtube (es gratis) click aquí (opens new window)
  2. Si estás viendo un video no olvides regalar un 👍 like y comentario 🙏🏼
  3. También puedes ser miembro del canal de Youtube click aquí (opens new window)
  4. Puedes adquirir cursos premium en Udemy 👇🏼👇🏼👇🏼 ¿Quiéres apoyar los directos? - Curso de HTML + CSS + Bootstrap 5 + Git y más UDEMY (opens new window) - Curso de React + Firebase UDEMY (opens new window) - Curso Vue.js + Firebase UDEMY (opens new window)

WARNING

# Planificación

  • Formularios no controlados
  • Formularios controlados
  • React Hook Form

# Recursos

Extensiones Navegador (React Developer Tools):

# Formulario no controlado

  • uncontrolled (opens new window): En la mayoría de los casos, te recomendamos usar Componentes controlados para implementar formularios.
  • En un componente controlado, los datos del formulario son manejados por un componente React.
  • La alternativa son los componentes no controlados, donde los datos del formulario son manejados por el propio DOM.
  • Para escribir un componente no controlado, puedes usar una referencia para que obtengas los valores del formulario desde el DOM.

Referencias y el DOM

  • refs (opens new window): Las referencias proporcionan una forma de acceder a los nodos del DOM o a elementos React creados en el método de renderizado.
  • useRef (opens new window): useRef devuelve un objeto ref mutable cuya propiedad .current se inicializa con el argumento pasado (initialValue). El objeto devuelto se mantendrá persistente durante la vida completa del componente. :::
import { useRef } from "react";

const FormularioNoControlado = () => {
    const formulario = useRef(null);

    // Formulario no controlado
    const handleSubmit = (e) => {
        console.log(formulario.current);
        e.preventDefault();
    };

    return (
        <div className="container mt-2">
            <form onSubmit={handleSubmit} ref={formulario}>
                <input
                    className="form-control mb-2"
                    type="text"
                    placeholder="Ingrese un TODO"
                    name="todoNombre"
                    defaultValue="Tarea #01"
                />
                <textarea
                    className="form-control mb-2"
                    type="text"
                    placeholder="Ingrese un TODO"
                    name="todoDescripcion"
                    defaultValue="Descripción tarea #01"
                />
                <select
                    className="form-control mb-2"
                    name="todoEstado"
                    defaultValue="completado"
                >
                    <option value="pendiente">Pendiente</option>
                    <option value="completado">Completado</option>
                </select>
                <button className="btn btn-primary" type="submit">
                    Agregar
                </button>
            </form>
        </div>
    );
};

export default FormularioNoControlado;

# FormData

import { useRef } from "react";

const FormularioNoControlado = () => {
    const formulario = useRef(null);

    // Formulario no controlado
    const handleSubmit = (e) => {
        // console.log(formulario.current);
        e.preventDefault();

        const datos = new FormData(formulario.current);

        // spread operator: permite a un elemento iterable ser expandido
        // copia cada uno de sus elementos
        console.log(...datos.entries());

        // El método Object.fromEntries() transforma una lista de pares con [clave-valor] en un objeto.
        const objetoDatos = Object.fromEntries([...datos.entries()]);

        // console.log(objetoDatos);
        if (!objetoDatos.todoNombre.trim()) {
            return console.log("vacío");
        }

        console.log("pasó las validaciones!");
        formulario.current.reset();
    };

    return (
        <div className="container mt-2">
            <form onSubmit={handleSubmit} ref={formulario}>
                <input
                    className="form-control mb-2"
                    type="text"
                    placeholder="Ingrese un TODO"
                    name="todoNombre"
                    // defaultValue="Tarea #01"
                />
                <textarea
                    className="form-control mb-2"
                    type="text"
                    placeholder="Ingrese un TODO"
                    name="todoDescripcion"
                    // defaultValue="Descripción tarea #01"
                />
                <select
                    className="form-control mb-2"
                    name="todoEstado"
                    // defaultValue="completado"
                >
                    <option value="pendiente">Pendiente</option>
                    <option value="completado">Completado</option>
                </select>
                <button className="btn btn-primary" type="submit">
                    Agregar
                </button>
            </form>
        </div>
    );
};

export default FormularioNoControlado;

# Formularios controlados

  • controlled (opens new window)
  • Los componentes React que rendericen un formulario también controlan lo que pasa en ese formulario con las subsecuentes entradas del usuario.
  • Ahora vamos a poder detectar los campos input en tiempo real.

Ejemplo casi casi:

import { useState } from "react";

const Form = () => {
    const [todo, setTodo] = useState({
        todoNombre: "",
        todoDescripcion: "",
        todoEstado: "pendiente",
    });

    const handleSubmit = (e) => {
        e.preventDefault();

        console.log(todo);
    };

    return (
        <div className="container mt-2">
            <form onSubmit={handleSubmit}>
                <input
                    className="form-control mb-2"
                    type="text"
                    placeholder="Ingrese un TODO"
                    name="todoNombre"
                    value={todo.todoNombre}
                    onChange={(e) =>
                        setTodo({ ...todo, todoNombre: e.target.value })
                    }
                />
                <textarea
                    className="form-control mb-2"
                    type="text"
                    placeholder="Ingrese un TODO"
                    name="todoDescripcion"
                    value={todo.todoDescripcion}
                    onChange={(e) =>
                        setTodo({ ...todo, todoDescripcion: e.target.value })
                    }
                />
                <select
                    className="form-control mb-2"
                    name="todoEstado"
                    value={todo.todoEstado}
                    onChange={(e) =>
                        setTodo({ ...todo, todoEstado: e.target.value })
                    }
                >
                    <option value="pendiente">Pendiente</option>
                    <option value="completado">Completado</option>
                </select>
                <button className="btn btn-primary" type="submit">
                    Agregar
                </button>
            </form>
        </div>
    );
};

export default Form;

Ahora si se ve más bonito:

import { useState } from "react";

const Form = () => {
    const [todo, setTodo] = useState({
        todoNombre: "",
        todoDescripcion: "",
        todoEstado: "pendiente",
    });

    const handleSubmit = (e) => {
        e.preventDefault();

        console.log(todo);
    };

    const handleChange = (e) => {
        // console.log(e.target.name);
        // console.log(e.target.value);
        // setTodo({ ...todo, [e.target.name]: e.target.value });
        setTodo((prev) => ({
            ...prev,
            [e.target.name]: e.target.value,
        }));
    };

    // console.log(todo);

    return (
        <div className="container mt-2">
            <form onSubmit={handleSubmit}>
                <input
                    className="form-control mb-2"
                    type="text"
                    placeholder="Ingrese un TODO"
                    name="todoNombre"
                    value={todo.todoNombre}
                    onChange={handleChange}
                />
                <textarea
                    className="form-control mb-2"
                    type="text"
                    placeholder="Ingrese un TODO"
                    name="todoDescripcion"
                    value={todo.todoDescripcion}
                    onChange={handleChange}
                />
                <select
                    className="form-control mb-2"
                    name="todoEstado"
                    value={todo.todoEstado}
                    onChange={handleChange}
                >
                    <option value="pendiente">Pendiente</option>
                    <option value="completado">Completado</option>
                </select>
                <button className="btn btn-primary" type="submit">
                    Agregar
                </button>
            </form>
        </div>
    );
};

export default Form;

# Checkbox






 
 
 






<div className="form-check">
    <input
        className="form-check-input"
        type="checkbox"
        id="flexCheckDefault"
        checked={todo.todoCheck}
        onChange={handleChange}
        name="todoCheck"
    />
    <label className="form-check-label" htmlFor="flexCheckDefault">
        Dar prioridad
    </label>
</div>
const [todo, setTodo] = useState({
    todoNombre: "",
    todoDescripcion: "",
    todoEstado: "pendiente",
    todoCheck: false,
});

const handleChange = (e) => {
    const { name, value, checked, type } = e.target;

    setTodo((prev) => ({
        ...prev,
        [name]: type === "checkbox" ? checked : value,
    }));
};

console.log(todo);

# Pequeña validación

const [error, setError] = useState(false);

const handleSubmit = (e) => {
    e.preventDefault();

    const { todoNombre, todoDescripcion } = todo;

    // pequeña validación
    if (!todoNombre.trim() || !todoDescripcion.trim()) {
        console.log("campos vacíos");
        setError(true);
        return;
    } else {
        setError(false);
    }

    // Enviar todo a un array!
};

const PintarError = () => (
    <div className="alert alert-danger">Todos los campos obligatorios</div>
);
<div className="container mt-2">
    <h2>Formulario</h2>
    {error && <PintarError />}
    ...
</div>

Todo junto:

import { useState } from "react";

const Form = () => {
    const [todo, setTodo] = useState({
        todoNombre: "",
        todoDescripcion: "",
        todoEstado: "pendiente",
        todoCheck: false,
    });

    const [error, setError] = useState(false);

    const handleChange = (e) => {
        const { name, value, checked, type } = e.target;

        setTodo((prev) => ({
            ...prev,
            [name]: type === "checkbox" ? checked : value,
        }));
    };

    const handleSubmit = (e) => {
        e.preventDefault();

        const { todoNombre, todoDescripcion } = todo;

        // pequeña validación
        if (!todoNombre.trim() || !todoDescripcion.trim()) {
            console.log("campos vacíos");
            setError(true);
            return;
        } else {
            setError(false);
        }

        // Enviar todo a un array!
    };

    const PintarError = () => (
        <div className="alert alert-danger">Todos los campos obligatorios</div>
    );

    return (
        <div className="container mt-2">
            <h2>Formulario</h2>
            {error && <PintarError />}
            <form onSubmit={handleSubmit}>
                <input
                    className="form-control mb-2"
                    type="text"
                    placeholder="Ingrese un TODO"
                    name="todoNombre"
                    value={todo.todoNombre}
                    onChange={handleChange}
                />
                <textarea
                    className="form-control mb-2"
                    type="text"
                    placeholder="Ingrese un TODO"
                    name="todoDescripcion"
                    value={todo.todoDescripcion}
                    onChange={handleChange}
                />
                <select
                    className="form-control mb-2"
                    name="todoEstado"
                    value={todo.todoEstado}
                    onChange={handleChange}
                >
                    <option value="pendiente">Pendiente</option>
                    <option value="completado">Completado</option>
                </select>
                <div className="form-check">
                    <input
                        className="form-check-input"
                        type="checkbox"
                        id="flexCheckDefault"
                        checked={todo.todoCheck}
                        onChange={handleChange}
                        name="todoCheck"
                    />
                    <label
                        className="form-check-label"
                        htmlFor="flexCheckDefault"
                    >
                        Dar prioridad
                    </label>
                </div>
                <button className="btn btn-primary" type="submit">
                    Agregar
                </button>
            </form>
        </div>
    );
};

export default Form;

# Validación

Si lo que estás buscando es una solución completa incluyendo validación, tener en cuenta los campos visitados y manejar el envío del formulario, Formik (opens new window) es una de las opciones populares.

También existen otras como: react hook form (opens new window) la cual veremos a continuación.

# React hook Form

  • Estamos trabajando en esta sección 👷‍♂️👷‍♀️
  • 👍 al video 😍
Last Updated: 4/27/2022, 8:04:34 AM