React. Crear el custom hook useModal()
Cómo crear un custom hook useModal para añadir modales a tu aplicación
En este artículo quiero enseñaros la forma en que podemos crear un custom hook que nos permita añadir modales a nuestra aplicación.
Con la aparición de los React Hooks se abrió un mundo de posibilidades a la hora de desarrollar aplicaciones con React pues no sólo están a disposición los hooks que trae React “out of the box” sino que a partir de ellos podemos crear nuevos como veremos a continuación con el hook useModal(). Así que, ¡vamos a ello!
1. Introducción
En este tutorial vamos a aprender a crear un React Hook para un componente encargado de pintar ventanas modales en nuestra aplicación.
La gestión de ventanas modales siempre ha sido un quebradero de cabeza al desarrollar aplicaciones pues éstas tienen que respetar los principios mínimos de accesibilidad y además a menudo requieren pensar mucho la estructura del DOM de nuestra aplicación.
Por ejemplo, es muy común recurrir a la propiedad CSS z-index para posicionar nuestra modal. Sin embargo, esta propiedad depende también del padre y cómo éste se posiciona con respecto al resto de modales de la página por lo que a menudo es mejor recurrir a soluciones como los React Portals de cara a añadir las modales al final de la etiqueta <body>
del DOM.
Para el desarrollo de este tutorial empezaré un proyecto desde cero instalado mediante:
npx create-react-app react-hooks-modal
y emplearé la librería Bloomer para crear las modales, pues el objetivo de este tutorial es ver cómo podemos crear el custom hook useModal() no el modelado de las mismas. Podéis instalarla mediante yarn
:
yarn add bloomer
Bloomer también requiere la librería Bulma para los estilos, por lo que también será necesario instalarla:
yarn add bulma
e importar sus estilos.
Una vez instaladas ambas librerías, vamos a crear el componente CustomModal
para que os familiaricéis con su comportamiento:

Este componente emplea los componentes proporcionados por Bloomer para crear una modal cuyo título, estado, contenido y acción al cerrarse son recibidos como propiedades.
Una vez creada podremos emplearla en cualquier para de nuestra aplicación del siguiente modo:

Y si ejecutamos el proyecto obtendremos algo similar a lo siguiente:

2. Hook useModal
Ahora que ya hemos creado nuestro componente para gestionar ventanas modales es el momento de entrar en la parte interesante de este tutorial: la creación del custom hook useModal().
Este hook tendrá el siguiente aspecto:

- Estará basado en el hook
useState
de modo que podamos controlar en qué momento la modal se encuentra visible y cuando no. - Crearemos una función auxiliar denominada
toggle
que se encargará de alternar el estado de la propiedadisOpened
. - El hook
useModal
devolverá un array con 3 elementos: el estado de la modal (isOpened
), la función para establecer el valor deisOpened
(setModalOpen
) y la funcióntoggle
ya mencionada.
¿Y cómo podemos usar el hook useModal
?
Lo primero de todo conviene recordar que cada vez que se emplea la función devuelta por el hook useState
se provoca automáticamente un nuevo render del componente funcional que está usando el hook.
Por tanto, dentro de nuestro componente App
podemos crear un botón que al pulsarlo llame a la función toggle
de modo que se invoca a la función setIsOpened
y la modal pase al estado “abierta”.

- Tras ejecutar
useModal
obtenemos las 3 variables devueltas por nuestro custom hook. - La función
setIsModalOpened
la empleamos dentro de la propiedadhandleClose
de nuestro componenteCustomModal
de modo que al presionar sobre “cerrar” el estado del hook se actualice. - La variable
isModalOpened
la empleamos como valor para la propiedadisActive
de nuestro componenteCustomModal
. - Finalmente la función
toggleModal
(el tercer valor devuelto por el hook useModal()) la empleamos como handler del botón encargado de mostrar la modal.
3. Pasar información a useModal
Todo lo anterior está muy bien pero tiene varias limitaciones:
- No podemos saber qué elemento lanzó la modal,
- Y lo más importante, no podemos pasar información a la modal.
Por ejemplo, imaginemos que tenemos una lista de elementos. Puede ser que necesitemos que al pulsar sobre uno de ellos se lance una modal con los detalles de cada elemento por lo que sería conveniente tener un mecanismo por el que pasar información al hook useModal
y de ahí al componente CustomModal
.
Para ello vamos a construir otro custom hook llamado useModalWithData
con el siguiente aspecto:

Este hook toma como punto de partida el hook useModal
que creamos anteriormente (otra de las ventajas de los React Hooks es la posibilidad de reutilizarlos unos dentro de otros lo cual permite construir hooks complejos a partir de otros más simples) y extiende su funcionalidad del siguiente modo:
- Primero emplea el hook
useModal
para declarar el estado de la modal y poderlo modificar posteriormente. - Emplea de nuevo el hook
useState
para almacenar la información relativa a la modal y así poderla pasar posteriormente al componenteCustomModal
. - Crea un nuevo método llamado
customSetIsModalOpened
de modo que cuando queramos cerrar la ventana se invoque la funciónsetData
procedente del hookuseState
para limpiar la información almacenada poniéndola anull
.
¿Y cómo podemos usar el hook useModalWithData
?
Bien, una vez que ya tenemos creado el hook useModalWithData
vamos a suponer que tenemos una lista de artículo que se renderea con su título y un botón asociado que mostrará una modal con el título y el cuerpo del mismo.
Para ello vamos a crear los siguientes componentes.
ArticleDetail
para mostrar el título y cuerpo de un artículo.ArticleList
para mostrar la lista de artículos.Blog
que mostrará el componenteArticleList
y empleará el hookuseModalWithData
para mostrar la información de cada artículo.
Vamos a verlos uno a uno.

Este componente no requiere mayor explicación. ArticleDetail
recibe un artículo como propiedad y muestra su información.

ArticleList
recibe 3 propiedades:
- La lista de artículos.
- La función
setModalData
devuelta por el hookuseModalWithData
con el fin de establecer la información de la modal una vez que se pulsa un artículo de la lista. - La función
setIsModalOpened
con el fin de mostrar la modal cuando se pulsa un artículo de la lista.
Por lo demás, este componente recibe la lista de artículos, itera sobre ella y añade a cada uno de los artículos un botón para lanzar la modal y establecer el artículo seleccionado de modo que la modal “sepa” el detalle del artículo que tiene que pintar.

Finalmente el componente Blog
recibe la lista de artículos y ejecuta el hook useModalWithData
para renderear los siguientes componentes:
CustomModal
cuyo contenido será el componenteArticleDetail
el cual recibirá como propiedadarticle
el valormodalData
procedente del hook.ArticleList
al que pasará las funciones procedentes deuseModalWithData
con el fin de actualizar el estado de la modal y su información.
De este modo, cuando se pincha el botón de un artículo:
- Se llama a la función
setData
con lo que la propiedaddata
del hookuseModalWithData
pasa a ser el artículo seleccionado. - Se llama a la función
setIsModalOpened
que establece atrue
el valor de la propiedadisModalOpened
del hook. - Y puesto que son funciones asociadas al hook
useState
se provoca un nuevo render de modo que la modal es mostrada con la información del artículo seleccionado.
Conclusiones
Creo que este tipo de artículos sirven para mostrar el potencial de los hooks y cómo podemos adaptarlos para resolver problemas que anteriormente requerían de más código y más complejidad en lo que a estructura se refiere.
Los siguientes pasos una vez creado el hook useModal
podrían ser ver la forma de compatibilizarlo con React Portals de cara a solucionar problemas de accesibilidad en aplicaciones complejas.
Por lo demás, podéis ver el código completo en el siguiente repositorio por si queréis trastear.
¿Quieres recibir más artículos como este?
Si te ha gustado este artículo te animo a que te suscribas a la newsletter que envío cada domingo con publicaciones similares a esta y más contenido recomendado: 👇👇👇