¿Por qué un useEffect es un mal lugar para llamar una API?

En el presente artículo discutiremos por qué uno de los dos hooks más importantes, y que incluso muchos desarrolladores consideran como indispensable para el desarrollo en React, es useEffect, no es el mejor lugar ni la mejor opción para hacer llamadas a APIs externas del proyecto.


Las decisiones respecto al diseño del hook useEffect por parte del equipo de React siemrpe han estado rodeadas de debate y controversias. Algunas personas adoran este hook y otras lo detestan. Si no tienes demasiada experiencia en el mundo de React, definitivamente es complicado entender cómo realmente funciona un useEffect, y sobre todo es sencillo caer en un error muy popular usualmente conocido como "Infinite Render Loop".


De primeras, este código se ve bien, pero lo que ocurrirá al ejecutar el proyecto es que se imprimirá "¡Hola!" cada vez que se haga un re-render del mismo. Por esta razón, useEffect tiene un segundo parámetro, el cual es un array de "dependencias", o de elementos de los que depende que el código dentro de este hook se renderice. Para que el código dentro del hook se ejecute sólo una vez, es necesario pasar como segundo parámetro un array vacío.


Esto, en primer lugar, también parece arreglado y funcionando correctamente, pero en verdad sigue sin estar del todo bien...

En modo de desarrollo, si utilizas lo que normalmente llamamos Strict Mode de React (que básicamente se llama envolviendo el código de la app en el tag <React.StrictMode>), el código dentro de un useEffect con un array de dependencias vacío se ejecuta dos veces en lugar de solamente una. Esto puede dar graves problemas, especialmente discutiendo sobre el problema de tener que llamar a una API dentro de un useEffect.

Pese a tener el problema, puedes intentar arreglarlo con un custom hook como el que se presenta a continuación.


Sin embargo, podemos afirmar que esta no es una solución óptima, y honestamente tampoco es la forma más elegante de solucionar el problema anteriormente planteado.

De acuerdo con la documentación oficial de React, useEffect ejecuta el código dentro de sí cuando la aplicación se renderiza completamente (o el componente en el que se encuentra el useEffect finaliza de renderizarse por su propia cuenta). Por esta razón, cuando llamamos una API dentro del mismo, esta llamada se realiza al finalizar de renderizarse la aplicación.

Esta no es la forma más óptima de obtener datos por medio de una API, ya que el tiempo que toma la llamada a la misma y la carga de los datos que nos interesan se va luego de renderizar la aplicación. Esto claramente consumirá muchos recursos. Por esta razón, está claro que la solución óptima es que se carguen datos de una API de forma paralela a la renderización de la aplicación. Para esto tenemos la existencia de React Query. Esta librería tiene un hook llamado useQuery, el cual llama a la información solicitada mientras la aplicación se está renderizando. Un ejemplo de cómo utilizar este hook es el siguiente.


La forma de hacer esto con useEffect es bastante más engorrosa y larga (y para peor, no funciona del todo bien). Esta llamada se realizaría algo así.


Mirando la sintaxis podemos ver que react query use query no sólo se ejecuta instantáneamente mientras se carga la página, sino que también maneja un montón de cosas como estados de carga, estados de error y datos reales en un solo objeto devuelto por react query. Además, volver a ejecutar/invalidar la consulta es tan sencillo como ejecutando la siguiente línea de código.


Otras librerías interesantes que también resuelven este problema son SWR, URQL y Apollo Client.

Como conclusión, hacer llamadas a una API desde un useEffect puede ser propenso a errores o francamente lento. Así que es mejor evitarlo a menos que sea necesario. Lo que realmente quieres es que alguna biblioteca se encargue de obtener los datos por ti.

- Zant.

No hay comentarios:

Con la tecnología de Blogger.