Introducción a React Hooks

Pequeña introducción a React Hooks, crea componentes mucho más cortos, legibles y aprende sus ventajas y desventajas.

Introducción a React Hooks
Photo by Efe Kurnaz on Unsplash

En 2018 se dio a conocer una nueva característica en la librería de React llamada Hooks, esta fue presentada en la ReactConf por el equipo de Facebook y debo admitir que me encantó la simplicidad y la nueva forma de escribir nuestros componentes en React, pero para aquel entonces aún estaba muy beta, así que decidí no profundizar demasiado y esperar algo estable, ya que por experiencia he escuchado a muchos desarrolladores que les molesta los cambios fuertes entre las versiones pre-alfa, alfa, beta … etc, nunca debemos implementar versiones no estables en productos reales, pero tampoco es malo jugar un poco con ellas, en este caso React Hooks ya no es un juguete, en la versión v16.8 ya podemos usarlo para crear nuestras aplicaciones web.

Antes de hablar de una nueva tecnología siempre debemos preguntarnos si esta tiene una razón del porque fue creada, con el fin de saber si es la solución a un problema, mejora o simplemente algo innovador.

React Hooks nace de un problema, en realidad nace de muchos problemas que enseguida voy a explicarte, ya que esto te dará un mayor contexto y eventualmente aplicarás este feature de una forma más consciente.

Problemas de React:

Estos problemas no son bugs, pero se pueden generar.

Reusabilidad de lógica

Este problema consiste en que en React es difícil compartir o reusar lógica entre componentes, existen soluciones para esto como componentes de alto orden (HOC) o componentes basados en Render Props, cualquiera de estas dos formas nos permiten compartir lógica entre componentes, pero tienen algunos problemas en común ya que son muy difíciles de mantener y tenemos que reescribir código cada vez que se quiera crear un componente de este tipo, debido a estos problemas debemos ser muy cuidadosos al realizar algún cambio para no generar nuevos bugs.

Componentes Gigantes

Todo componente inicia con pocas líneas de código, pero según con el transcurrir de requerimientos y nuevas necesidades te encontrarás con componentes demasiado grandes, dificultando la legibilidad, pero este problema también radica a los ciclos de vida de un componente, ya que entre más complejo es el componente más ciclos de vida este puede tener y estos ciclos de vida hacen que un componente crezca exponencialmente, veamos un ejemplo sencillo:

Ahora analicemos un poco este componente, ya que este es demasiado grande para lo simple que es, adicionalmente en los ciclos de vida de React a veces nuestro código tiende a ser redundante y repetitivo, sin opción de poder compartirlo fácilmente a otros componentes, que seguramente necesiten las mismas líneas de código.

Las clases son difíciles de entender

Este es un problema al que todo desarrollador de React se ha enfrentado, ya que por ejemplo cuando empiezas a escribir un componente seguramente lo crearás como una función, que recibe props, el problema es cuando por algún motivo tienes que realizar un cambio que afecte directamente a ese componente, entonces te ves obligado a tener un estado y obligatoriamente tienes que pasar ese componente a una clase.

Adicionalmente las clases en React tienen definido unos métodos y buenas prácticas a seguir, si eres nuevo en React seguramente cometas el error de no crear el constructor de la clase o no hacer el bind de una función, tal vez cambies el estado cuando el componente se esté renderizando, son errores que pueden generar bugs y demoras en el desarrollo de nuestra aplicación.

Los anteriores problemas son resueltos con React Hooks, veamos como:

Primero definamos que son Hooks en React, Hooks son funciones que se agregaron al API de React, las cuales no alteran o modifican las APIs y funcionalidades existentes, lo cual es genial ya que no tenemos que actualizar componentes o hacer una configuración extra para que esto funcione, sólo actualizamos las siguientes librerías (react@16.8.0 y react-dom@16.8.0), tanto react y react-dom deben estar mínimo en la versión 16.8, teniendo actualizadas nuestras dependencias ya podemos usar Hooks sin ningún problema.

La mejor forma de entender un nuevo concepto es con ejemplos sencillos, luego ya podemos ir subiendo el nivel de dificultad, vamos a presentar a nuestro primer Hook, este es useState una función que básicamente reemplazará a nuestro setState, con la ventaja que no tenemos que tener un componente como clase para poder hacer un cambio de estado a nuestro componente, veamos un ejemplo simple:

Supongamos que tenemos un componente que recibe por props el nombre de nuestro usuario, sería algo como esto:

Ahora supongamos que el nombre del usuario sea editable, normalmente tendríamos que pasar este componente a una clase para tener un estado dentro del componente y hacer un handleChange de un input para poder editar el nombre.

Realicemos la comparación entre escribir un componente de tipo clase y otro como función, pero utilizando useState que es nuestro nuevo Hook:

🚨Parar ver Hooks en vivo: https://codesandbox.io/s/w223p99p7

Utilizando useState reducimos nuestro código significativamente, también es más fácil la lectura del código ya que simplemente son funciones, veamos como funciona, lo primero que hacemos es declarar dos variables que nos retorna useState podemos nombrarlas como nosotros queramos, la primera variable será nuestro estado, este puede ser un objeto, array, string … etc, nuestra segunda variable es la función con la que podemos cambiar nuestro estado y adicionalmente useState recibe un único parámetro y es el estado inicial de nuestro estado.

Espero te haya quedado claro este primer Hook llamado useState, pero probablemente tengas ciertas dudas, una de ellas puede ser si puedes utilizar Hooks con componentes de tipo clase, o que hacer si necesito utilizar algún ciclo de vida de React dentro de una función con Hooks, cuál debería usar Hooks o clases, para responder a ello veamos primero las reglas que tiene Hooks.

Reglas de Hooks

  • Debemos declarar nuestros Hooks en un orden superior, es decir al inicio de nuestra función.
  • No puedes utilizar Hooks dentro de un componente de tipo clase, ya que no es posible.
  • No puedes llamar Hooks dentro un condicional, bucles o funciones anidadas, ya que React toma el orden en que fueron declarados cada Hook, guardando una referencia por cada uno.

Seguramente es posible necesites usar algún ciclo de vida para realizar por ejemplo un llamado a un API, actualizar tu componente o agregar y eliminar eventos del DOM, estos eventos son categorizados como efectos secundarios y para ello podemos utilizar un nuevo Hook llamado useEffect el cual reemplazaría los siguientes ciclos de vida como el componentDidMount, componentDidUpdate y el componentWillUnmount.

Efectos con o sin limpieza

React categoriza los efectos secundarios mencionados anteriormente como efectos con limpieza o efectos sin limpieza, los efectos sin limpieza son todos aquellos los cuales nos despreocupamos una vez los invoquemos, un ejemplo clásico es el llamado a un API o realizar algún cambio en DOM y los efectos con limpieza son todos aquellos que necesitamos realizar una acción antes de que el componente sea desmontado es decir un event Listener o suscripciones que de no ser limpiadas ralentizan nuestra aplicación, veamos un ejemplo de estos efectos secundarios utilizando clases vs un componente en función con useEffect:

RandomPokemon con clases:

🚨Puedes verlo en vivo: https://codesandbox.io/s/o2m9pq59

Este ejemplo es perfecto para mostrar las ventajas de useEffect y useState justos, aquí tenemos dos componentes donde RandomPokemon se encarga de obtener el id de un pokémon de manera aleatoria y el componente Pokemon realiza un request segun el id que llegue vía props, adicionalmente el tamaño de la imagen del pokémon es relativa según el alto del navegador, vamos a pasar esto a Hooks y dando una explicación detallada.

Primero vamos a reescribir el componente RandomPokemon quedando de la siguiente manera:

Eliminamos la clase y lo dejamos como función, agregamos un estado con useState, que anteriormente ya habíamos explicado, una vez comprendes Hooks es muy fácil reescribir un componente y simplificar código.

Ahora vamos con nuestro componente Pokemon el cual es mucho más complejo ya que tiene varios ciclos de vida, pero con useEffect queda mucho más limpio y legible:

🚨OMG Pruebalo en vivo: https://codesandbox.io/s/yj8250404x

Anteriormente con clases teníamos que invocar dos veces nuestro llamado al API, ya que el componentDidMount se ejecuta solo una vez después del primer render y componentDidUpdate no se ejecuta en el primer render pero si cuando una props cambia, con useEffect simplificamos esto ya que es una función que se ejecuta en cada render después de que el componente esté montado en el DOM o en pocas palabras una vez se haya renderizado, incluso si es nuestro primer render, es decir que cuando el componente cambie de props o un estado interno, ejecutará nuevamente la función useEffect obteniendo un nuevo pokemon, adicionalmente si nuestro efecto requiere un limpieza podemos hacer que este devuelva una función, esta se ejecutará antes de que el componente sea desmontado y allí podemos hacer la limpieza si es necesario.

Pero nuestro código tiene un gran error, cuando el API nos responde con un nuevo pokémon entonces realizamos un cambio de estado, esto conlleva a que el componente vuelva hacer un render y por ende la función useEffect es nuevamente ejecutada volviendo a ejecutar el llamado al API, creando un ciclo infinito innecesario, este es un de los casos donde no queremos que nuestro useEffect se ejecute en cada render, obviamente React pensó en una solución para esto veamos cómo:

El cambio es muy simple ya que useEffect recibe un segundo argumento donde podemos enviar una arreglo con las dependencias que este tendrá para ser ejecutado, es decir que nuestro efecto solo será ejecutado si nuestro IdPokemon cambia, dándonos el control sobre este efecto.

Puedes ver el código en vivo aquí: https://codesandbox.io/s/yj8250404x

En el inicio de este artículo entendimos algunos problemas que tiene React, realicemos un chequeo para ver si con Hooks los logramos resolver:

  • Componentes Gigantes => Resuelto: Con Hooks podemos omitir las clases y por ende los ciclos de vidas, haciendo nuestros componentes sean más cortos.
  • Las clases son difíciles de entender => Resuelto: Si implementamos Hooks, no tenemos que lidiar con las clases, nuestro componentes son basados en solo funciones y es mucho más fácil leerlos y escribirlos de esta manera.
  • Reusabilidad de lógica => undefined: Creo que este problema no se ha aclarado del todo, ya que no he mostrado un ejemplo claro de cómo reusar lógica, React creo los Hooks con el fin de reusarlos para otros componentes, en el ejemplo anterior en nuestro useEffect que declaramos realizamos dos efectos, uno fue el llamado a un API y el otro escuchar evento, React no recomienda realizar en un useEffect varios efectos secundarios, lo mejor es tenerlos por separados ya que teniéndolos de esta manera podemos hacer algo como esto:

Primero separemos nuestros efectos

Ahora lo que tenemos que hacer para rehusar un Hook, la manera mas fácil es es hacer que este funcione independientemente, por ejemplo nuestro Hook que escucha el evento resize del navegador, necesita ser envuelto en una función ya a través de funciones lo podemos utilizar donde queramos, veamos como queda esta función:

Si analizas esta función es un minicomponente que se encarga de retornar el estado del alto del navegador, permitiéndonos compartirlo a otros componentes que necesiten la misma lógica, te invito a que realices esta extracción aquí.

Con esta breve introducción sólo hemos podido abarcar dos Hooks del API de React, pero sin lugar a duda son los más importantes y posiblemente las que utilizarás repetitivamente, explicaremos los demás Hooks en un próximo capítulo.

Conclusión:

Para concluir quisiera aclarar que React no recomienda que sobre escribas toda tu aplicación a Hooks, ya que las clases seguirán funcionando sin ningún problema, un consejo que te puedo dar es crear nuevos componentes con Hooks, para aquellos componentes pequeños donde los puedas aplicar fácilmente, creo que Hooks será el futuro pero necesita madurar un poco más, espero este artículo te haya ayudado a entender esta nueva mejora y para finalizar déjame saber en los comentarios si te gustó o tienes alguna duda.

Gracias por leer este articulo no olvides seguirnos en redes sociales para estar al tanto de nuevos contenidos.