DEV Community

Matías Hernández Arellano
Matías Hernández Arellano

Posted on • Updated on • Originally published at matiashernandez.dev

React useEffect ¿Por que el arreglo de dependencias es importante?

React useEffect es quizá el hook que más confusiones genera a la hora de utilizarlo.

Algunas de esas confusiones se debe al intento de comparar su funcionamiento con los estados del ciclo de vida de un componente de clase, algo que aclaro en este post anterior

Recomendado:

¿Qué son los hooks?

Algunos errores comunes al utilizar React hooks.

El hook useEffect recibe dos argumentos, una funcion/callback que define el efecto deseado y un listado/arreglo de valores que definen las dependencias del efecto.

Estas dependencias le sirven a React para saber cuándo o más bien por qué el efecto debe ejecutarse.

Internamente useEffect "observa" este listado de dependencias y cuando uno de los valores de ellas cambia el efecto es emitido. Esto te permite optimizar la ejecución del efecto.

Mantén en mente que React realiza una comparación utilizando Object.is para determinar si hubo un cambio en uno de los elementos. Si necesitas hacer una comparación "profunda" puedes utilizar este hook useDeepCompareEffect

El equipo de React provee un plugin de eslint que ayuda a identificar cuando hay dependencias no identificadas por medio de la regla: react-hooks/exhaustive-deps

En general un efecto es una función que ejecuta cierta lógica para sincronizar el estado interno del componente con un estado externo (si, no me canso de repetirlo 🤷‍♂️).

useEffect(() => {
        fetch("/api/data").then(
            res => setState(res.data)
        )
    }, [setState])
Enter fullscreen mode Exit fullscreen mode

Y por que las dependencias son importantes?

Simple! Por que las dependencias son la forma de controlar cuando el efecto se ejecuta o no. Recuerda. No se trata de si el efecto ocurre al montar el componente (o cualquier otro "momento"), si no, de por qué se ejecuta (cambio en un valor de una dependencia?

Y ¿por qué debo escribir todas las dependencias del efecto?

Si tu efecto utiliza un valor dentro de su lógica pero no lo declaras como dependencia entonces "algo huele mal"(code smell)

El plugin de eslint reportará la dependencia faltante como un warning. Entonces ¿Por qué es tan importante si sólo se reporta como un warning?.

Bueno, es un bug que en cualquier momento volverá a morderte.

Tu efecto funciona incluso sin declarar la dependencia por que la función/callback definida funciona como un closure y es capaz de utilizar el valor externo a su scope.

Si miramos el mismo ejemplo anterior, podemos escribirlo sin dependencias o con una lista vacía (lo que indica que se ejecutará sólo una vez)

useEffect(() => {
        fetch("/api/data").then(
            res => setState(res.data)
        )
    }, [])
Enter fullscreen mode Exit fullscreen mode

Pero, piénsalo así, estas declarando una función que trabaja con ciertos valores pero no le estas dando acceso directo a esos valores!! No es extraño?

¿Estás diciendo que tu función usa un valor pero que no depende de él?

¿Entonces que hacer?

Hay que redefinir la lógica de tu efecto para que solo utilice los valores de los que realmente dependa.

¿Cómo? Una forma es extraer la lógica hacia una función externa y utilizar esta nueva función como dependencia del efecto.

Te dejo algunos muy buenos artículos sobre useEffect:

Si te gustó este post considera unirte al newsletter MicroBytes para recibir microcursos sobre desarrollo web.
También puedes ver más contenido en @eggheadio

Y finalmente apoyar mi trabajo invitandome un café

Discussion (8)

Collapse
duxtech profile image
dux

Entonces, es buena practica listar en nuestro arreglo de dependencias todas las variables y funciones que esten siendo usadas en el callback de useEffect? Saludos

Collapse
matiasfha profile image
Matías Hernández Arellano Author

Exacto!.. hacerle caso al plugin de eslint.

Collapse
whil profile image
Ivan García

Es posible hacer una petición fetch sin pasarle una dependencia? Eso sería buena práctica o no?

Collapse
matiasfha profile image
Matías Hernández Arellano Author

Si no agregas las dependencias (y si realmente no tiene dependencias) entonces ese efecto se ejecutará solo una vez.
Por lo general este caso de uso es para obtener datos y después guardarlos en algún estado, por lo tanto, si tendrías una dependencia. La función para definir ese estado proviniente de useState que es ene efecto idempotente y no iniciada un nuevo render.

Collapse
llermaly profile image
llermaly

entonces en tu ejemplo sería recomendable mover la función fetch fuera del useEffect? asumiendo que en la mayoria de los casos este fetch podría venir acompañado de más cosas como un dispatch .

Collapse
matiasfha profile image
Matías Hernández Arellano Author

El problema de mover fetch fuera del efecto es que ahora esa función que crearás será dependencia del efecto, y si no es idempotente entonces será creada en cada re-render por lo que el efecto se emitirá constantemente.
Puedes usar React.useCallback para evitar esto.

Collapse
llermaly profile image
llermaly

Mi pregunta es más que nada porque al meter todo dentro del useEffect me sugiere agregar el dispatch en el array de dependencias y se siente extraño, es normal que así sea?

Thread Thread
matiasfha profile image
Matías Hernández Arellano Author

Bueno dispatch es una función "especial". React te asegura que no cambiará entre renders (es idempotente) por lo que, en este caso particular, no afecta su presencia (o ausencia) en las dependencias