Introducción a React Hooks

Kilian Medina
Nowports Tech and Product
8 min readMay 10, 2021

--

Hooks es una adición que salió en la versión 16.8 de React. Los Hooks permiten usar el estado y otras funciones sin escribir una clase, resolviendo problemas ligados a React, como reducir la complejidad de los componentes y crear un Component Hell.

Pero, ¿qué es un Hook?

Un Hook es una función especial que nos permitirá conectarnos a características de React para trabajar con métodos especiales, los cuales nos permitirán manejar el estado de mejor forma, sin depender de clases.

Debemos tener en cuenta algunas reglas al implementarlos, las cuales son:

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

Conociendo esto, en este pequeño articulo introductorio, vamos a ver un par de ejemplos básicos.

Como primer paso, empezaremos creando un pequeño proyecto para poder realizar ejemplos de los principales Hooks que nos ofrece React.

useState()

Este Hook nos ayudará a manejar el estado en componentes creados como funciones. Revisemos el siguiente ejemplo, que implementa la lógica de un botón:

Como podemos observar, en la primera línea traemos useState para poder utilizarlo en el componente.

useState manejará el estado y también se encargará de realizar el cambio del mismo. ¿Cómo se implementa? Declaramos una constante que desestructura dos elementos: el primero es el estado (darkMode) y el segundo es la función que se encargará de cambiarlo(setDarkMode). Por último, pasamos el estado inicial de la variable a useState().

Nuestro estado puede ser de los siguientes tipos: string, boolean, number, float, null, undefined, objet o array.

Después de realizar la lógica del estado en el botón, solo tenemos que llamar a esa función que sustituye setState, pasando ahora la función de useState para realizar el cambio de estado haciendo clic (cambiar el estado true/false).

useEffect()

Con este Hook nos olvidaremos de la estructura de ciclos de vida en los componentes y en su defecto los veremos como efectos.

Antes, en React (versiones inferiores a la 16.8) disponíamos de varias funciones heredadas de la clase Component, que nos permitían acceder a diferentes momentos del ciclo de vida de nuestro componente (montaje, actualización y desmontaje).

Con la llegada de este Hook, se pueden acceder a los eventos más usados desde una única función, tales son componentDidMount, componentDidUpdate y componentWillUnmount.

useEffect unifica tres métodos asociados al ciclo de vida de nuestro componente. ¿Cómo diferenciamos cada uno de estos métodos?

Este Hook, al igual que todos, son funciones. En este caso, recibe dos parámetros: el primero corresponde a un callback o función y el segundo un arreglo de dependencias. El callback no recibe ningún parámetro, solamente nos sirve para ejecutar código en el momento de que se produzca el efecto deseado. Por otro lado, el segundo parámetro es opcional y, dependiendo de su valor, el efecto se ejecutará.

Veamos un pequeño ejemplo implementando useEffect al hacer una llamada a una API publica:

Al igual que con useState, tenemos que importar nuestro Hook para poder usarlo en el componente. Primero creamos un estado con su función para cambiar/guardar los datos que estamos consumiendo de la API y lo inicializamos como un arreglo vacío.

Como se mencionó anteriormente, este Hook es una función compuesta por dos parámetros. El primero es una función anónima, donde haremos el fetch de la API que consume los datos para mostrarlos posteriormente. En este caso, realizamos el fetch para después llamar a la función set de useState y así guardar los datos que acabamos de obtener.

El segundo es una variable que se estará escuchando en dado caso que se ejecute un cambio. En este ejemplo, donde no es necesario que haya un cambio, solo necesitemos ejecutar nuestro useEffect cuando el componente se monte (componentDidMount si usaramos class components). Como segundo argumento le pasamos un arreglo vacío.

Por último, con la información que ya vive dentro de nuestro estado inicial, podemos realizar un .map() para mostrar la información gráficamente.

useContext()

Context provee una forma de pasar datos a través del árbol de componentes sin tener que pasar props manualmente en cada nivel.

En vez de estar pasando datos a través de cada uno de los hijos, lo que hace context es crear un estado global, lo cual nos va a ser útil para los datos que deban compartirse entre componentes. Se usa en temas, autentificación, idioma, entre otros.

Para poder administrar el estado global en los componentes funcionales, utilizaremos el Hook useContext. Veamos el siguiente ejemplo:

Dentro de un archivo nuevo, creamos un nuevo “contexto” para poder manejar el estado global, en este caso un color de tema. Después, en nuestro archivo index importaremos este nuevo context para englobar toda la aplicación mediante un provider donde encapsula toda la información. En este caso, pasaremos un valor para así cambiar el color de otro componente.

Después de englobar toda la aplicación, cualquier componente que esté dentro de la misma podrá acceder a la información que contenga el provider. Veamos como se implementa useContext en un ejemplo anterior:

  1. Importamos nuestro Hook.
  2. También importamos el ThemeContext, creado previamente esto para poder utilizar ambos y hacer uso de este contexto dentro del archivo. Con esto, traeremos el valor que asignamos dentro del provider.
  3. Creamos una nueva variable, en la cual asignamos nuestro ThemeContext para poder hacer uso del valor antes mencionado.
  4. Agregamos un estilo a la etiqueta h1 y así podremos ver ese valor en nuestro render, en este caso el texto de la etiqueta en color rojo.

useReducer()

Este Hook es una alternativa a useState. Este acepta un reducer de tipo (state, action) => newState y devuelve el estado actual emparejado con un método dispatch.

useReducer algunas veces es preferible a useState, cuando se tiene una lógica compleja que involucra múltiples subvalores o cuando el próximo estado depende del anterior. useReducer te permite optimizar el rendimiento para componentes que activan actualizaciones profundas.

Veamos como se implementa incorporándolo al ejemplo anterior, para agregar una nueva lista de elementos favoritos a partir de la llamada que hacemos con useEffect:

  1. Agregaremos el hook useReducer para poder hacer uso del mismo.
  2. Se crea un estado inicial, en este caso un arreglo vacío que iremos llenando con la información seleccionada.
  3. Se crea el reducer (favoriteReducer), que es una función que usa switch para identificar el metodo a usar este recibe state y action.

state es el estado actual, action es el objeto con el método que queremos ejecutar junto con el contenido, action.type es el método a ejecutar y action.payload es el contenido nuevo que queremos manejar. Por ejemplo, “ADD_TO_FAVORITE “ toma el estado actual y le agrega el contenido de payload.

4. Incorporamos el hook useReducer al componente:

const [favorites, dispatch] = useReducer(favoriteReducer, inicialState);

favorite es el nombre del valor de lectura. dispatch es el nombre de la función para llamar a los métodos y useReducer toma dos datos: el primero es el reducer que creamos anteriormente y el segundo parámetro es el estado inicial.

El siguiente paso es crear la función que llamará al dispatch (handleClick), este contiene el type, que es el nombre que agregamos a nuestro reducer para poder identificarlo, y el payload, que es el contenido que se manejara al correr el método.

Después incorporamos en nuestro render un botón, el cual manda a llamar al dispatch y al ejecutarse manda los datos del caracter en la función. Esta información se mandada al reducer y de ahí al state final en favorites. Por ultimo hacemos el render del contenido de arreglo favorites.

useMemo()

Como sabemos, la memoria de javascript no es infinita, gastarla excesiva o innecesariamente puede causar que el rendimiento de nuestra aplicación se vea afectada y esto puede dar una mala experiencia al usuario final.

Al implementar el Hook useMemo, evitamos cálculos innecesarios en nuestro código. Guardamos el resultado de nuestros cálculos cada vez que los hacemos para no tener que repetirlos en el futuro, ahorrando tiempo a cambio espacio de almacenamiento. Esto quiere decir que useMemo nos devuelve un valor memorizado.

Veamos un ejemplo de este Hook implementando un buscador en el componente que modificamos anteriormente, esto para memorizar la búsqueda que realizaremos:

Primero creamos un useState para encargarnos de esa búsqueda. Agregamos el input donde se realizará la misma, el valor será el estado inicial (search) del nuevo useState y también agregaremos el onChange para mandar a llamar la función de búsqueda (handleSearch).

Después crearemos nuestra función para filtrar los elementos que coinciden con la búsqueda que estamos realizando en el input (filteredCharacters), donde implementaremos el Hook useMemo. Dentro de ella realizamos la lógica para llevar a cabo este proceso, pero además este Hook recibe otro parámetro el cual escuchará (como useEffect) cuando cambie el render de los elementos o el valor de search. Así recordará los valores de los mismos.

Algo de suma importancia para implementar este Hook es escribir nuestro código para que funcione sin useMemo y después agregarlo para optimizar el rendimiento. En el futuro, React puede “olvidar” algunos valores previamente memorizados y recalcularlos en el próximo renderizado, por ejemplo, para liberar memoria para componentes fuera de pantalla.

En conclusión para esta pequeña introducción, React Hooks es una alternativa al desarrollo con clases. Esto no quiere decir que lo mejor es migrar toda nuestra aplicación a Hooks. Mi recomendación es implementarlos poco a poco en nuevos componentes que vayamos creando para así realizar este cambio de manera continua y no de golpe.

Espero que este artículo pueda ayudarles a comprender esta mejora y cómo funcionan algunos de ellos.

Referencia: https://es.reactjs.org/docs/hooks-reference.html

--

--