Cómo crear formularios dinámicos en React: paso a paso

Go to Homepage

Creando formularios dinámicos en React

Cuando necesitamos diseñar formularios complejos en React, muchas veces nos encontramos con la necesidad de que se vayan adaptando en tiempo real a las acciones que el usuario está realizando. Para ello, es esencial crear formularios dinámicos, que sean capaces de hablar directamente con el estado del componente, y que eviten hacer renderizaciones innecesarias.

En este tutorial, vamos a ver cómo crear formularios dinámicos en React, paso a paso y desde cero.

Lo primero que vamos a hacer es crear un componente base, que nos permita renderizar los diferentes campos del formulario. Para ello, utilizaremos el hook useState de React, que nos permitirá almacenar en el estado del componente el valor actual de cada campo.

import React, { useState } from "react";

const Field = ({ label, value, setValue }) => {
    return (
        <label>
            {label}:
            <input
                type="text"
                value={value}
                onChange={(e) => setValue(e.target.value)}
            />
        </label>
    );
};

export default Field;

Este componente recibe tres props: label, que es el texto que se mostrará como etiqueta del campo; value, que es el valor actual del campo; y setValue, una función que actualizará el valor del campo en el estado del componente.

Ahora, vamos a crear el componente del formulario en sí. Para nuestro ejemplo, vamos a crear un formulario para registrar usuarios, con campos para el nombre, el correo electrónico y la contraseña.

import React, { useState } from "react";
import Field from "./Field";

const UserForm = () => {
    const [name, setName] = useState("");
    const [email, setEmail] = useState("");
    const [password, setPassword] = useState("");

    const handleSubmit = (e) => {
        e.preventDefault();
        // Lógica para enviar el formulario
    };

    return (
        <form onSubmit={handleSubmit}>
            <Field label="Nombre" value={name} setValue={setName} />
            <Field label="Email" value={email} setValue={setEmail} />
            <Field label="Contraseña" value={password} setValue={setPassword} />
            <button type="submit">Enviar</button>
        </form>
    );
};

export default UserForm;

En este componente, utilizamos useState para crear tres estados distintos, uno por cada campo del formulario. Después, en el retorno del componente, creamos un formulario que utiliza el prop onSubmit para llamar a la función handleSubmit cuando se envíe el formulario.

Dentro del formulario, simplemente renderizamos tres componentes Field, uno por cada campo del formulario, y un botón para enviar el formulario.

En la función handleSubmit, podemos agregar la lógica que necesitemos para enviar el formulario a algún lugar, como una API o una base de datos.

Y eso es todo: hemos creado un formulario dinámico en React, paso a paso y desde cero. Este formulario es capaz de adaptarse en tiempo real a las acciones del usuario, gracias al uso de useState y a la separación de la lógica de renderizado y la lógica de estado. Ahora, podemos extender este ejemplo para crear formularios aún más complejos y con un mayor número de campos.

Entendiendo el estado y las props

Una de las características más importantes de React es su habilidad para manejar estados y props. Es necesario entender estos conceptos para poder crear formularios dinámicos en React paso a paso.

En React, el estado es un objeto que contiene información que puede cambiar a lo largo del tiempo. Cuando el estado cambia, React se actualiza y vuelve a renderizar la interfaz gráfica. El estado se puede definir en el constructor del componente o mediante una propiedad state.

Las props son objetos que contienen información que se pasa de un componente a otro. Los props son “read-only”, es decir, no pueden ser modificados fuera del componente que los recibe. Los props se pueden pasar a un componente mediante la propiedad props.

Entonces, ¿cuál es la diferencia entre el estado y las props? El estado pertenece a un componente en particular, y sólo ese componente puede modificarlo. Las props se pasan de un componente a otro, y el componente que las recibe no puede modificarlas. El estado cambia durante la vida de un componente, mientras que las props se mantienen iguales.

Veamos un ejemplo para entender mejor lo anterior. Supongamos que queremos crear un formulario que muestre el nombre y la edad de una persona. Para ello, creamos un componente llamado “Persona”.

import React, { Component } from "react";

class Persona extends Component {
    constructor(props) {
        super(props);

        this.state = {
            nombre: "",
            edad: 0,
        };

        this.handleChangeNombre = this.handleChangeNombre.bind(this);
        this.handleChangeEdad = this.handleChangeEdad.bind(this);
    }

    handleChangeNombre(event) {
        this.setState({ nombre: event.target.value });
    }

    handleChangeEdad(event) {
        this.setState({ edad: event.target.value });
    }

    render() {
        return (
            <div>
                <label htmlFor="nombre">Nombre:</label>
                <input
                    type="text"
                    value={this.state.nombre}
                    onChange={this.handleChangeNombre}
                />

                <label htmlFor="edad">Edad:</label>
                <input
                    type="number"
                    value={this.state.edad}
                    onChange={this.handleChangeEdad}
                />
            </div>
        );
    }
}

export default Persona;

En el constructor de este componente, inicializamos el estado con dos valores: nombre y edad. También definimos dos métodos que se llaman cada vez que los valores de los inputs cambian. Estos métodos modifican los valores del estado.

En el render del componente, mostramos dos inputs que muestran el valor del estado correspondiente. Además, agregamos eventos que llaman los métodos handleChangeNombre y handleChangeEdad cada vez que el usuario modifica los inputs.

Ahora, podemos utilizar este componente en otro componente para crear nuestro formulario.

import React, { Component } from "react";
import Persona from "./Persona";

class Formulario extends Component {
    render() {
        return (
            <div>
                <Persona />
            </div>
        );
    }
}

export default Formulario;

Cómo manejar eventos en los componentes

En la creación de formularios dinámicos en React, uno de los aspectos más importantes es el manejo de eventos en los componentes para poder capturar la interacción del usuario con la interfaz y actualizar los datos en tiempo real.

Existen ciertos eventos que se pueden utilizar en los componentes de React, como onClick, onChange, onSubmit, onFocus, entre otros. Cada uno de estos eventos se activará cuando el usuario interactúe con el componente de una forma específica.

Para manejar estos eventos en nuestros componentes, primero debemos asegurarnos de que el componente tenga un estado que pueda ser modificado por el evento en cuestión. Luego, debemos agregar el manejo de evento dentro del método correspondiente del componente.

Por ejemplo, si queremos manejar el evento onChange en un componente de input para actualizar un valor del estado, podemos hacerlo de la siguiente manera:

import React, { useState } from "react";

function MyComponent() {
    const [inputValue, setInputValue] = useState("");

    const handleInputChange = (event) => {
        setInputValue(event.target.value);
    };

    return (
        <div>
            <input
                type="text"
                value={inputValue}
                onChange={handleInputChange}
            />
        </div>
    );
}

En este caso, primero creamos un estado llamado inputValue utilizando el hook de useState. Luego, creamos una función handleInputChange que se encargará de actualizar el estado inputValue con el nuevo valor que se ingrese en el input. Finalmente, agregamos el evento onChange al input y le asignamos la función handleInputChange.

Otro ejemplo podría ser el manejo del evento onClick en un botón para hacer una solicitud HTTP y actualizar el estado con la respuesta:

import React, { useState } from "react";
import axios from "axios";

function MyComponent() {
    const [data, setData] = useState(null);

    const handleClick = async () => {
        const response = await axios.get(
            "https://jsonplaceholder.typicode.com/todos/1"
        );

        setData(response.data);
    };

    return (
        <div>
            <button onClick={handleClick}>Obtener datos</button>
            {data && (
                <div>
                    <p>{data.title}</p>
                    <p>{data.completed ? "Completado" : "Pendiente"}</p>
                </div>
            )}
        </div>
    );
}

En este caso, creamos un estado llamado data que inicialmente es null. Luego, creamos una función handleClick que hace una solicitud HTTP utilizando axios y actualiza el estado data con la respuesta. Finalmente, agregamos el evento onClick al botón y le asignamos la función handleClick. Si el estado data no es null, mostramos los datos obtenidos en la interfaz.

El manejo de eventos en los componentes de React es esencial para crear formularios dinámicos y actualizar los datos en tiempo real. Debemos asegurarnos de que los componentes tengan un estado que pueda ser modificado por el evento y agregar el manejo de evento dentro del método correspondiente del componente. Con esto, podremos crear formularios con una experiencia de usuario óptima y dinámica.

Utilizando métodos de ciclo de vida para mejorar la funcionalidad

React nos ofrece la posibilidad de utilizar los métodos de ciclo de vida para manejar estados y mejorar la funcionalidad de nuestras aplicaciones. Estos métodos nos permiten ejecutar código en momentos predefinidos del ciclo de vida de un componente, como por ejemplo, cuando se carga o actualiza.

El primer método que vamos a ver es componentDidMount(). Este método se llama justo después de que el componente haya sido montado en el DOM. Es un buen momento para hacer peticiones a una API o inicializar una librería externa.

class MiComponente extends React.Component {
    componentDidMount() {
        // Hacer una petición a una API
        // Inicializar una librería externa
    }

    render() {
        // ...
    }
}

Otro método interesante es componentDidUpdate(). Este método se llama cuando el componente ha sido actualizado, ya sea porque se ha cambiado su estado o debido a un cambio en sus props. Es un buen momento para actualizar cualquier información que dependa del estado o las props actuales.

class MiComponente extends React.Component {
    state = { valor: "" };

    componentDidUpdate(prevProps, prevState) {
        if (this.state.valor !== prevState.valor) {
            // Actualizar información dependiente del estado
        }
    }

    render() {
        // ...
    }
}

Si necesitas hacer alguna limpieza antes de que el componente sea desmontado del DOM, puedes utilizar el método componentWillUnmount().

class MiComponente extends React.Component {
    componentDidMount() {
        // Hacer algo antes de desmontar
    }

    componentWillUnmount() {
        // Limpiar antes de desmontar
    }

    render() {
        // ...
    }
}

Por último, si necesitas hacer alguna actualización en las props antes de que sean utilizadas, puedes utilizar el método componentWillReceiveProps(). Este método se llama antes de que el componente reciba nuevas props.

class MiComponente extends React.Component {
    componentWillReceiveProps(nextProps) {
        if (this.props.valor !== nextProps.valor) {
            // Actualizar información dependiente de las props
        }
    }

    render() {
        // ...
    }
}

Los métodos de ciclo de vida son herramientas poderosas para mejorar la funcionalidad de nuestras aplicaciones en React. Utilízalos de manera adecuada para manejar estados, actualizar información y hacer limpieza antes de que los componentes sean desmontados del DOM.

Integrando validación de datos para una mejor experiencia de usuario

Cuando creamos formularios dinámicos en React, es importante no solo considerar la interactividad del usuario, sino también asegurarnos de que los datos ingresados sean válidos y se ajusten a ciertos criterios. En este artículo, te mostraremos cómo integrar la validación de datos para una mejor experiencia de usuario.

Para comenzar, debemos agregar una nueva dependencia a nuestro proyecto de React. Utilizaremos la librería react-hook-form para manejar la validación de datos en nuestros formularios. Puedes instalarla a través de npm de la siguiente manera:

npm install react-hook-form

Luego, importamos los componentes necesarios desde la librería y creamos nuestro formulario, agregando la propiedad onSubmit y la función handleSubmit. También agregamos una variable de estado llamada errors para manejar los errores de validación.

import React, { useState } from "react";
import { useForm } from "react-hook-form";

function Form() {
    const { register, handleSubmit, errors } = useForm();
    const [submitting, setSubmitting] = useState(false);

    const onSubmit = (data) => {
        setSubmitting(true);
        console.log(data);
    };

    return (
        <form onSubmit={handleSubmit(onSubmit)}>
            <input
                type="text"
                name="username"
                ref={register({ required: true })}
            />
            {errors.username && <span>This field is required</span>}

            <input
                type="email"
                name="email"
                ref={register({ required: true, pattern: /^\S+@\S+$/i })}
            />
            {errors.email && <span>Please enter a valid email</span>}

            <button type="submit" disabled={submitting}>
                Submit
            </button>
        </form>
    );
}

En este ejemplo, hemos agregado dos campos de entrada: username y email. Para cada uno, utilizamos la propiedad ref para registrarlo con react-hook-form y especificamos las reglas de validación necesarias. Para el campo username, simplemente lo marcamos como requerido. Para el campo email, agregamos una regla de validación adicional que utilice una expresión regular para asegurarnos de que sea un correo electrónico válido.

Finalmente, agregamos una condición para mostrar mensajes de error según se requiera, utilizando la variable de estado errors que nos proporciona react-hook-form.

Integrar la validación de datos en nuestro formulario nos permite mejorar la experiencia del usuario al proporcionar mensajes de error claros y útiles. También nos aseguramos de que los datos ingresados se ajusten a ciertos criterios, lo que nos ayuda a mantener la calidad de nuestros datos.

Al crear formularios dinámicos en React, la validación de datos es un aspecto importante a tener en cuenta para mejorar la experiencia del usuario. Con la librería react-hook-form, podemos integrar la validación de datos fácilmente en nuestro formulario, lo que nos permite proporcionar mensajes de error claros y útiles para garantizar que nuestros datos sean de alta calidad. ¡Agrega esta funcionalidad a tus formularios y mejora la calidad de tus datos y la experiencia de tus usuarios!

Otros Artículos