JavaScript. ¿Qué es Debouncing, y cómo implementarlo en Gatsby?

Programar animaciones e interacciones en JavaScript es tentador y sencillo, pero muchas veces te encuentras con un problema usual implementado interacciones con el ratón. Sobretodo interacciones relacionadas con el “scroll”. Un ejemplo práctico sería cuando tienes que desarrollar un listado con “paginación”, en el que la paginación es una función del scroll infinito.

¿Cuál es el problema?

El problema es que, haciendo un simple scroll, la funcionalidad de scroll infinito puede hacer que tu código haga peticiones, o llamadas múltiples a la API. Esto puede hacer que la aplicación deje de funcionar en el frontend, o incluso en el backend, si la API atacada tiene límites de peticiones, o simplemente hacer que el rendimiento del navegador se vea afectado.

¿Cómo solucionarlo?

Es aquí donde entra en escena la función de debounce en JavaScript! Debounce te permite controlar el número de peticiones que un usuario puede hacer en una determinada acción de scroll. Debounce es, por tanto, una práctica usada para mejorar el rendimiento de navegador que permite ejecutar una función una sola vez, en la frecuencia de tiempo especificada desde la última vez que se ha llamado esta misma función.

¿Qué es una función debounce?

Para resumir, y cómo hemos dicho antes, una función debounce, o antirrebote es una función que permite limitar la frecuencia en que una función se puede disparar o ejecutar.  

Esto ayuda a aliviar la carga de los servicios que se pueden llamar desde el controlador de eventos. La idea general de debouncing es empezar con 0 (zero) timeout, si la función rebotada es llamada nuevamente, reiniciar el contador al retraso especificado, y en caso de timeout, llamar la función rebotada.

Ejemplos de aplicación

También como ya hemos referido anteriormente, un ejemplo de aplicación sería cuando tengas un formulario con un etiqueta de tipo <input> y quieres controlar el evento Change con sugerencias. Otro - nuestro ejemplo - sería cuando quieras cargar nuevos elementos de un listado de artículos en pantalla. Un tercero ejemplo aun seria si tienes un “listener” para redimensionar la pantalla, que calcula las dimensiones.

Si el usuario ejecuta varias veces alguna de estas acciones, la función responsable por ejecutarlas se disparará varias veces y el rendimiento de tu sitio web, o aplicación web se verá afectado.

Ejemplo en Gatsby

Podrás implementar tu función antirebote manualmente, pero gracias a la comunidad existen varias bibliotecas que te permiten solucionar este problema. Una de estas herramientas es el método debounce() de lodash.

debounce() de lodash es un método que permite retrasar la llamada de tu función hasta que no pasen los milisegundos que hayas definido, desde la última vez que la función “rebotada” haya sido llamada. ¡Creo que se trata de un método muy potente y completo que vale la pena echar un vistazo!

¿Cómo implementarlo?

Implementar lodash en Gatsby es muy sencillo. Por el alcance de este artículo, doy por hecho ya tienes programado cómo recuperar datos desde tu servidor o API, y además tu aplicación ya está funcionando. Utilices fetch, axios, o superagent, el resultado final debería ser el mismo.

Veamos cómo implementarlo:

1.Instalamos lodash.debouce

Recuerda que nuestro objetivo es utilizar el evento onscroll para verificar si el usuario ha hecho scroll. En este caso, no hasta la parte inferior de la ventana (window), sino hasta la parte inferior de un elemento. La idea es que cuando el scroll alcance el final de este elemento, nuestra función intente cargar más elementos.

2. Importamos debounce y ReactDOM

En nuestro componente de React, creamos la función scrollHandler() responsable por controlar el evento, utilizando debounce. Por ejemplo:

El método debounce de lodash accepta otros argumentos además de la función que pretendes “rebotar”. Estos son los argumentos que utilizamos en este artículo:

  • func. La función a rebotar
  • wait. Un número en milisegundos a retrasar. En nuestro caso es 100 milisegundos.

Si tu método fetchArticles() está bien definido, con las actualizaciones correctas de los estados (states) hechas, por ejemplo los estados de “hasMore”, “loading” y “error”, eso es todo lo que necesitas.

Sin embargo, como estamos añadiendo el evento a un elemento y no a la ventana (window), vale la pena recordar también que necesitas declarar el “handler” en tu elemento.

Utilizamos refs para poder acceder al elemento posteriormente

Y utilizar el constructor de React para vincular el controlador de eventos al componente. Por ejemplo:

Enlazamos la función a la instancia del componente

También debes asegurar que tu componente tenga el evento de scroll adjuntado. Utilizaremos el método addEventListener()  una vez esté montado el componente. El componente también necesita conocer la altura del elemento para las interacciones. Para ello utilizaremos los métodos de ciclo de vida de React que ya conoces, en el caso componentDidMount(). Igualmente utilizaremos ReactDOM de la siguiente manera:

Y para terminar utilizamos el método componentWillUnmount() para remover el evento del elemento.

Conclusión

¡Y eso es todo por hoy! Espero que a partir de hoy sea más fácil utilizar debounce en tus aplicaciones y debounce sea parte de tu listado de buenas prácticas, ya sea utilizando tu propia función, o alguna otra biblioteca de JavaScript existente.

¡Si tienes alguna pregunta, no dudes en dejar un comentario!

Foto: Adina Voicu en Pixabay

Fuentes: