¿Cómo crear componentes genéricos Forms y Fields para reducir código repetitivo con React y TypeScript? | Parte I

Cómo-crear-componentes-genéricos-Forms-y-Fields-reducir-código-repetitivo-React-y-TypeScript-Parte-I-Itequia

¿Cómo crear componentes genéricos Forms y Fields para reducir código repetitivo con React y TypeScript? | Parte I

Los formularios son un tema importante porque son extremadamente comunes en las aplicaciones que construimos. En este artículo, aprenderemos cómo crear formularios usando componentes controlados por React y veremos cómo construir componentes genéricos para ayudarnos a minimizar y optimizar el código.

componentes-genéricos-Forms-y-Fields-Itequia

Además, la validación del lado del cliente es fundamental para la experiencia del usuario de los formularios que construimos, por lo que también cubriremos este tema. Enviar el formulario también es una consideración crítica. Cubriremos cómo manejar los errores de envío, así como el éxito de una forma genérica.

Por lo que, en esta serie de artículos, vamos a cubrir los siguientes temas:

  • Comprensión de los componentes controlados
  • Reducción del código repetitivo con componentes genéricos
  • Implementación de la validación
  • Envío de formularios

En React, librería de JavaScript que ya hemos visto en artículos anteriores, nosotros podemos usar componentes controlados para implementar un formulario, un componente controlado tiene su valor sincronizado con el estado en React, por medio de la función useState, que es parte de la API de Hooks.

En el ejemplo que mostraremos más abajo, Articulo.tsx, hemos realizado las siguientes acciones:

  • Agrupado los inputs y el botón “Guardar” en un form, así nosotros podemos invocar el submit al hacer click en el botón “Guardar” o al presionar la tecla Enter
  • Asignamos a la propiedad value de los inputs unos estados de react (inputNombreValue/setInputNombreValue y inputApellidoValue/setInputApellidoValue), esto es lo que se conoce componentes controlados, ya que estos elementos (input, checkbox, etc) tienen un control interno de su estado, proporcionada por la propia implementación HTML en el navegador, un input es capaz de mantener el valor escrito por el usuario, no obstante, useState de React se apropia de dicho estado, somos nosotros quienes controlamos el valor y renderización de su contenido
  • Hemos creado un método (handleInputNombreChange y handleInputApellidoChange) que se ejecuta cada vez que el evento change de un input se dispara con el fin de ir disponiendo del valor de los inputs constantemente, almacenándolos en nuestros respectivos useState
  • Hemos creado un método con el nombre requiredField para controlar si el campo nombre está vacío, en cuyo caso mostramos mensaje de error

Si no contásemos con un componente genérico tendríamos que estar repitiendo todo este código constantemente en cada una de las pantallas que se necesiten formularios, crear estados, detectar eventos de cambios de valores en los inputs, checkbox, validación de campos y todo tipo de código que nos podríamos ahorrar y optimizar con la creación de un componente genérico.

Es importante puntualizar, que para este artículo vamos a usar React y TypeScript juntos. React se define en sí mismo como una librería JavaScript de código abierto creada por Facebook para construir interfaces de usuario, sin embargo, cuando le sumamos el ecosistema de herramientas disponibles, es una solución completa para el desarrollo de aplicaciones web, móvil, escritorio e incluso realidad virtual.

¿Por qué usar React?

Con React nosotros podemos dividir nuestra aplicación en pequeños componentes reusables, componentes los cuales pueden tener su propia interface de usuario y comportamiento.

por-que-react-Itequia

React es una librería progresiva, es decir, aumentar la integración de componentes y frameworks en función de nuestras necesidades, por lo que se adaptará perfectamente a nuestro proyecto.

¿Qué conocimientos básicos debemos tener?

Partiendo de la base de que la curva de aprendizaje en React es más baja en comparación con otros frameworks/librerías, es importante tener conocimientos básicos de HTML, CCSS y JavaScript y para este artículo en concreto sería interesante disponer de conocimientos básicos de TypeScript.

¿Por qué TypeScript?

TypeScript no ofrece la posibilidad de tipar los datos, por tanto, nos proporciona un mayor control en tiempo de ejecución de todo nuestro código.

por-que-Typescript-Itequia

Por ejemplo:

const miVariableTexto: string;
const miVaribleNumero: number;

Reducción del código repetitivo con componentes genéricos

Cómo comentábamos anteriormente, en este artículo aprenderemos cómo crear formularios genéricos para ayudarnos a minimizar, reutilizar en otros proyectos con el consiguiente incremento de productividad y optimizar nuestro código gracias a la reutilización de nuestros componentes, todo ello, usando React y TypeScript.

En esta sección, vamos a crear un componente formulario genérico (FormGenerico.tsx) y componente campo genérico (FieldGenerico.tsx) que se encargará de manejar el estado de los valores (inputNameValue/setInputNameValue y inputApellidoValue/setInputApellidoValue), detección de eventos, validación de campos, etc, que hemos implementado anteriormente en Articulo.tsx , esto reducirá drásticamente el código necesario para implementar un formulario.

Pasos para la creación de un componente Formulario genérico:

  • Creamos un nuevo componente con el nombre FormGenerico
  • Definimos interface para los valores de los campos del formulario
export interface Values {

  [key: string]: any;

}

En este caso, la key será el nombre del campo y el value será el valor del campo, ejemplo:

{

nombre: “valor del input nombre”,

apellido:”valor del input apellido”

}
  • Incluir la propiedad children en dicho componente con el fin de poder renderizar el contenido anidado dentro del formulario (Contenido propio del componente que usará el FormGenerico y el FieldGenerico, en nuestro caso ArticuloUsandoFormGenerico.tsx)
  • Creamos useState para el valor de los fields, usando la interface creada anteriormente (Values)
const [values, setValues] = useState<Values>({});

Establecemos el estado inicial en un objeto literal vacío, values dispondrá de todos los valores de todos los inputs, en nuestro ejemplo la clave/valor del objeto sería:

{

       nombre: “valor del input nombre”,

apellido:”valor del input apellido”

  }

Pasos para la creación del componente FieldGenerico

El componente FieldGenerico, no deja de ser todo elemento que puede formar parte de un formulario, Input, Select, TextArea, Checkbox, etc. Así como conjunto de dichos elementos que sean usados a su vez como componentes en este FieldGenerico, al final, la esencia es la misma, mientras más componentes tengamos que puedan ser reutilizados, más productivos, mejor calidad de código y más control sobre nuestra aplicación tendremos.

Los pasos a seguir son:

  • Creamos un nuevo campo con el nombre FieldGenerico
  • Creamos las siguientes propiedades del componente:
interface Props {

 name: string;

 label?: string;

 type?: 'Text' | 'TextArea';

}
  • Renderizamos el componente FieldGenerico con la label
  • Renderizamos los controles según su type
{(type === 'Text') && (

            <input

              type={type.toLowerCase()}

              id={name}

              ....

          )}

          {type === 'TextArea' && (

            <textarea

              id={name}...

         

Compartiendo estado con React Context

Es importante destacar que el estado de los valores de un campo, se encuentra en el componente FormGenerico, pero se presenta y cambia en el componente FieldGenerico.

Gracias a React Context, FormGenerico puede compartir su estado con FieldGenerico, con context de React se posibilita pasar datos a través del árbol de componentes, sin tener que pasar propiedades manualmente en cada nivel, en este caso FormGenerico provee y FieldGenerico consume los valores que presenta FormGenerico.

Creando context en FormGenerico

En este punto, nos centraremos en quien provee, quien es la fuente de los valores que serán consumidos por el componente genérico FieldGenerico.

  • Añadimos la función createContext
import { FC, useState, createContext } from 'react';
  • Creamos una interface para nuestro contexto
interface FormContextProps {

  values: Values;

  setValue?: (fieldName: string, value: any) => void;

}

Nuestro context contendrá los valores del FormGenerico y la función para actualizarlos

  • Creamos el contexto
export const FormContext = createContext<FormContextProps>({

  values: {},

});

Creando proveedor de contexto

Ahora que ya hemos tenemos creado el contexto en FormGenerico, vamos a usar su componente Provider.

<FormContext.Provider

      value={{

        values,

        setValue: (fieldName: string, value: any) => {

          setValues({ ...values, [fieldName]: value });

        },

        ...

De esta manera, utilizamos su componente Provider, para dar acceso a dicho contexto a sus componentes hijos (FieldGenerico), para que puedan ser consumidos.

Y aquí acaba la primera parte de esta sección de artículos sobre cómo crear componentes genéricos con React y TypeScript para reducir el código repetitivo en nuestros proyectos.

Te esperamos en la segunda parte, en la que detallaremos cómo consumir un Context de FormGenerico, cómo implementarlo y en la que contaremos con un ejemplo completo.

Hugo Pasctual – Software Developer at Itequia