El uso de formularios en desarrollo web es fundamental a la hora de crear aplicaciones interactivas ya que con ellos podemos validar y enviar información a nuestros servidores. La verdad es que trabajar con formularios puede ser más desafiante de lo que pudiéramos creer.
Para crear un buen formulario, debemos tener en cuenta los siguientes aspectos:
- Accesibilidad: Millones de usuarios en el mundo sufren algún tipo de discapacidad y navegan los sitios web a través de herramientas diferentes al mouse y el teclado, por lo tanto, debemos tener en cuenta la semántica de los elementos HTML que usemos para crear el formulario, además no será suficiente usar las estrategias de validación convencionales propuestas por los navegadores.
- Validación: Cada campo que existe en el formulario puede tener unas reglas particulares. Unos campos pueden ser opcionales, otros obligatorios, también permiten ingresar correos electrónicos, pueden requieren valores mínimos o máximos, entre otros. Comunicar a todos los usuarios acerca de los valores permitidos en un campo específico es una función fundamental de las validaciones de campos.
- Serialización: Cuando un usuario ha terminado de diligenciar el formulario, su información se encuentra en algún espacio de memoria en el que usa la aplicación. Obtener esa información, manipularla y enviarla adecuadamente puede ser un reto en algunas ocasiones.
Objetivo
Una vez que termines de leer este artículo vas a entender las características de la creación de formularios web, serás capaz de implementar tus propios formularios, aprenderás acerca de patrones de diseño populares en React y, conocerás algunas de las bibliotecas más usadas para solucionar los retos mencionados anteriormente.
Outline
¿Cómo no aprender este tema puede impactar el trabajo (corto plazo) y la carrera (largo plazo) de un desarrollador?
No utilizar React adecuadamente para manipular formularios puede llevarnos a construir aplicaciones con problemas de testing, mantenibilidad, e incluso rendimiento.
¿Cómo este tema se relaciona con el panorama general del desarrollo web?
Los formularios son elementos fundamentales del ecosistema web, gracias a ellos almacenamos información ingresada por el usuario. Además, cumplen diferentes roles en un sitio o aplicación web, hacen parte del proceso de registro y autenticación de usuarios, también son usados para la creación, modificación y lectura de datos.
¿A quién está dirigido este artículo?
Este artículo está diseñado para personas que usan React en su día a día, que buscan escribir mejores formularios y, que quieran implementar soluciones con patrones de diseño modernos y usar bibliotecas populares que solucionan estos mismos problemas.
¿Que encontraras en este articulo?
- Patrones de React para crear formularios
- Componentes Controlados
- Componentes No Controlados
- Validación de formularios
- Validaciones síncronas
- Validaciones asíncronas
- Ecosistema de bibliotecas de formularios
- Probando Formik
- Probando React Hook Form
- Probando React Final Form
- Comentarios sobre accesibilidad en formularios
- Conclusiones
Patrones de React para crear formularios
Componentes Controlados
Un componente controlado es aquel que usa los cambios de estado o cambios de props
como fuente de verdad para representarse en el DOM
.
De manera más concreta, es un componente que mantiene una sincronización entre el estado de React y el valor del campo, si el estado cambia, el valor cambia.
Puedes pensar en el cómo un proceso cíclico:
Relación entre un componente, su cambio de estado y el estado en sí mismo
A continuación, tenemos nuestro primer componente controlado:
Si imprimimos la variable values
verás que el comportamiento del componente es actualizarse con estos valores cada que alguno de los campos cambia:
Cambio del estado al editar el campo de correo o contraseña:
Componentes No Controlados
Un componente no controlado, es aquel que no usa el estado o las props
para representarse en el DOM
, y, por el contrario, usa la API del DOM. La manera en la que React obtiene los valores es usando la API de REF.
Relación entre un componente, la API de REF y la API del DOM.
Los formularios en React son buenos casos de uso para aplicar el patrón de componentes no controlados.
Es importante mencionar que:
- Este componente no hace
re-render
por sí mismo, ya que no tiene cambios de estado. - Los valores de cada campo los gestiona la API del
DOM
, por lo tanto, React solo hace render y obtiene las referencias de los inputs usando la API deREF
.
Validación de Formularios
Las validaciones en los formularios buscan guiar y comunicar al usuario sobre los valores adecuados que cada uno de los campos espera almacenar. Los casos de uso son numerosos, a veces se busca que tenga un rango especifico de caracteres, otras veces queremos que cumpla un patrón de texto preciso, o quizás queremos que responda frente a un campo previamente ingresado.
Para calcular si los valores del campo son correctos o incorrectos podemos ejecutar una serie de evaluaciones en nuestra base de código que pueden ocurrir de manera síncrona o asíncrona, miremos de que se trata:
Validaciones Síncronas
Una validación síncrona es aquella que evalúa el estado del campo en el hilo principal de Javascript. La mayoría de las validaciones son de este tipo, y los casos de uso más normales son validaciones de correos electrónicos, nivel de seguridad de contraseña, y para generalizar, todo aquello que sea posible usando Regexp.
A continuación, estaremos implementando un formulario usando una validación síncrona.
A continuación, verás a nuestro componente validar el correo electrónico que estamos ingresando, y una vez el error deba comunicarse (onBlur) lo verás aparecer en acción.
Ejemplo de validación síncrona de un campo de correo electrónico:
Validaciones Asíncronas
Las validaciones asíncronas son aquellas que determinen el estado del campo usando algún servicio externo que bloquea el hilo principal de Javascript.
Suelen ser usados para comparar valores que ingresa el usuario contra una base de datos, verificar si una dirección es válida, si un correo no está en uso, si un nombre de usuario ya ha sido registrado, entre otros.
A continuación, estaremos implementando un formulario usando una validación asíncrona.
En este ejemplo dos cosas cambiaron:
- El tipo de evaluación que hacemos es asíncrono, en este caso tenemos estamos haciendo un llamado a un servicio que, para este ejemplo estamos simulando.
handleValidation
pasa a ser una función asíncrona. Luego de que el llamado al servicio concluya ocurrirá un cambio de estado con la respuesta del servidor (correo disponible o no).
Veamos la validación en acción:
Ejemplo de validación asíncrona de un campo de correo electrónico:
Ecosistema de bibliotecas de formularios
El uso de bibliotecas y frameworks es parte del día a día de un desarrollador frontend, el ecosistema de Javascript es bastante amplio y, gracias a ello una alta cantidad de soluciones ya han sido abstraídas y puestas a disposición de cualquier proyecto open source o privado.
El manejo de formularios en React no es la excepción, a continuación, te propongo que exploremos algunas de las bibliotecas más populares para el manejo de formularios en React.
En cada uno de los paquetes que veremos a continuación, analizaremos algunos aspectos fundamentales como:
Formik
Formik es una biblioteca exclusiva para el manejo de formulario en React y React Native. Se encarga de las abstracciones más comunes, es intuitiva, y finalmente es adoptable por su simplicidad y tamaño.
Su peso minificado y en GZIP es de: 13 kB
Está biblioteca ofrece dos modos de uso, la primera es usando un Provider
llamado Formik
y tiene algunas ventajas como poder usar los componentes que Formik ha abstraído como <Field />
, <ErrorMessage />
, entre otros.
La segunda opción es más minimalista y se usa través de la API de Hooks usando uno de ellos llamado useFormik
.
A continuación, usaremos useFormik
para construir un componente de formulario básico:
useFormik
tiene una gran variedad de parámetros que podemos suministrar para controlar el formulario de manera flexible.
En el snippet anterior:
- Importamos y ejecutamos dentro del componente el método
useFormik
, definiéndole el estado inicial y la función que debe ejecutarse cuando se guarde el formulario. useFormik
nos devuelve un objeto con diferentes métodos y atributos que definen el estado del formulario.handleSubmit
contiene la lógica que ejecutara el formulario al guardarsehandleChange
sincroniza el valor de los campos con el estado usando componentes controladosvalues
contiene los valores actuales del formulario- Le pasamos al formulario y los campos los métodos y valores descritos anteriormente. De esta manera el estado estará disponible para ser usado cada que el componente lo requiera.
- Cuando el evento de submit ocurre, la función
onSubmit
tiene los valores disponibles para ser usados.
React Hook Form
React Hook Form es una biblioteca construida sobre la API de React Hooks, está enfocada en el perfomance, la integración con otras bibliotecas de UI como react-datepicker
, downshift
, chakra
, entre otros.
Su peso minificado y en GZIP es de: 8.6 kB
Todo la API de react-hook-form
como lo dice su nombre, está basado en hooks. Su hook principal es useForm
.
A continuación, verás la implementación básica de un formulario de registro usando esta biblioteca.
En el snippet anterior:
- Importamos y ejecutamos dentro del componente el método
useForm
. useForm
nos retorna dos métodos,register
yhandleSubmit
.register
se usa en cada uno de los campos, está es la manera como se sincroniza el estado con el formulario.handleSubmit
se usa para especificar el método que debe de ejecutarse cuando el formulario es guardado.- Cada input usa
register
describiendo el identificador del campo. - Cuando el evento de submit ocurre, la función
onSubmit
tiene los valores disponibles para ser usados.
React Final Form
React Final Form es un wrapper de Final Form, una biblioteca agnóstica a frameworks que sirve para crear formularios en Javascript. Su implementación esta basada en el patrón de observador y de esta forma hace re-render
solo de los componentes que cambiaron.
Su peso minificado y en GZIP es de: 13.9 kB (Requiere instalar final-form
)
Como veremos a continuación React Hook Form funciona a través de Context API usando un componente <Form />
que a través de render props
nos retorna el estado actual del formulario y así, validar y manipular los campos a nuestras necesidades.
En el snippet anterior:
- Importamos y utilizamos el componente
<Form />
suministrando la función que se ejecutará cuando el componente sea guardado. - El contenido interno del componente
<Form />
es un render prop, o una función que proporciona propiedades y/o estado interno. - En nuestro ejemplo solo estamos usando el método
handleSubmit
que nos proporciona el render prop, sin embargo, en los parámetros de esa función podremos obtener información del estado del formulario, como por ejemplo, si está activo, si ya está siendo diligenciado, si tiene errores, etc. - Finalmente, React Final Form nos proporciona un componente
<Field />
que se sincroniza internamente con el contexto del componente<Form />
, este componente representado el<input />
usado en los ejemplos anteriores, sin embargo, tiene una API bastante flexible que permite integrar componentes existentes usandoinput
,select
, o inclusotextarea
.
Comentarios sobre accesibilidad en formularios
- Para mejorar la experiencia de la navegación en el formulario puedes crear una relación lógica entre el elemento
<label />
y el elemento<input />
a través de los atributosfor
(htmlFor
en React) eid
respectivamente. Esto permite que el<input />
hagafocus
cuando se seleccione el<label />
, esta técnica ayuda a las personas con discapacidades motoras a seleccionar el campo fácilmente, especialmente cuando usamoscheckbox
oradio button
. - En los ejemplos que vimos en código no le especificamos a los
input
s la propiedadaria-label
, ya que con la estrategia mencionada en el punto 1, elinput
usa comolabel
el contenido de la etiqueta<label />
a la cual se relacionó usando el atributofor
ohtmlFor
. Debes usararia-label
si por alguna razón tu<input />
no tiene un<label />
asociado, de lo contrario no será fácil de interpretar para una persona con discapacidades visuales. - La accesibilidad también se trata de escribir estilos adecuadamente, es por ello que nunca debes de usar
outline: none
. Eloutline
es ese contorno amarillo que se visualiza cuando un campo hacefocus
, y es usado para orientar a los usuarios que no usan elmouse
sobre donde están ubicados en tu sitio. - Si vas a indicarle alertas y/o errores a los usuarios de tu formulario es importante que no dependas solo de colores (generalmente amarillo y rojo respectivamente). Muchos usuarios con problemas de visión se apoyan en configuraciones que cambian el contraste de color en el navegador haciendo obsoleta la comunicación por colores, puedes compensarlo escribiendo buenos mensajes de alerta y error.
Conclusiones
El desarrollo web habilita la interactividad de los usuarios a través de HTML y Javascript, los formularios son un ejemplo de la capacidad que tiene el navegador para comunicarse con los usuarios de un sitio o aplicación. React es una biblioteca que facilita la creación de interfaces visuales entre ellas formularios, sin embargo, es fundamental tener buenas prácticas para garantizar una buena experiencia de usuario y capacidad de mantenimiento dentro de un equipo de desarrollo, es por ello que, hay que tener en consideración todo el público que puede usar nuestras aplicaciones. Todas las aplicaciones deberían ser fundamentadas sobre principios de accesibilidad, y no pensar en ellos como un feature al final del backlog del proyecto.
Espero que esta guía te haya sido de utilidad y te animo a que sigas aprendiendo acerca de React, formularios web y como hacer de la web un lugar equitativo para todos.