En términos simples, useEffect
permite ejecutar código después de que el componente se haya renderizado, y también ofrece una manera de limpiar esos efectos cuando el componente se desmonta o cuando cambian las dependencias especificadas.
import React, { useEffect } from 'react';
function MiComponente() {
useEffect(() => {
console.log('Componente montado');
// Cleanup opcional que se ejecuta cuando el componente se desmonta
return () => {
console.log('Componente desmontado');
};
}, []); // Array de dependencias vacío: el efecto solo se ejecuta en el montaje y desmontaje
return <div>Hola, soy un componente con useEffect</div>;
}
La estructura básica del useEffect
es la siguiente:
1. Función de efecto: La primera parte de useEffect
es una función que contiene el código que se ejecutará después de que React haya renderizado el componente.
2. Array de dependencias: La segunda parte (opcional) es un array que define cuándo debe volver a ejecutarse el efecto. Este array de dependencias le dice a React qué valores debe observar para determinar si debe ejecutar nuevamente el efecto.
useEffect
1. Montaje y Desmontaje: Cuando se pasa un array de dependencias vacío ([]
), el efecto se ejecuta solo una vez, similar a componentDidMount
en los componentes de clase. Si el efecto tiene un retorno, esa función se ejecuta cuando el componente se desmonta, equivalente a componentWillUnmount
.
2. Dependencias: Cuando se proporciona un array con variables, el efecto se ejecuta cada vez que alguna de esas variables cambie. Esto permite controlar cuándo React debe volver a ejecutar el efecto.
3. Actualización: Si se omite el array de dependencias, el efecto se ejecuta después de cada renderizado del componente, es decir, después de cada cambio de estado o de props. Esto no es ideal en la mayoría de los casos, ya que puede provocar comportamientos no deseados y afectar el rendimiento.
A continuación, se presentan algunos casos de uso comunes de useEffect
en los componentes de React.
Una de las aplicaciones más comunes de useEffect
es hacer solicitudes a APIs. En este caso, se usa para cargar datos cuando el componente se monta.
import React, { useState, useEffect } from 'react';
function DatosUsuario({ userId }) {
const [userData, setUserData] = useState(null);
useEffect(() => {
// Función asíncrona para obtener datos
const fetchData = async () => {
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`);
const data = await response.json();
setUserData(data);
};
fetchData();
}, [userId]); // El efecto se ejecuta cada vez que cambia el `userId`
return (
<div>
{userData ? (
<div>
<h2>{userData.name}</h2>
<p>Email: {userData.email}</p>
</div>
) : (
'Cargando...'
)}
</div>
);
}
En este ejemplo:
userData
para almacenar los datos del usuario.
useEffect
se usa para hacer una llamada a la API cuando el componente se monta o cuando cambia el valor de userId
.
[userId]
asegura que el efecto se ejecute solo cuando userId
cambie.
Puedes usar useEffect
para suscribirte a eventos y luego limpiar la suscripción cuando el componente se desmonta.
import React, { useEffect, useState } from 'react';
function VentanaSize() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
// Cleanup para remover el listener cuando el componente se desmonte
return () => {
window.removeEventListener('resize', handleResize);
};
}, []); // El efecto solo se ejecuta una vez cuando el componente se monta
return <p>Ancho de la ventana: {width}px</p>;
}
En este ejemplo:
useEffect
para añadir un listener de eventos resize
de la ventana.
window.removeEventListener
) elimina el listener para evitar fugas de memoria.
useEffect
no puede ser directamente una función asíncrona (async
), se pueden definir funciones asíncronas dentro de él y llamarlas. Otra opción es usar then
y catch
para manejar promesas.
Al igual que otros hooks en React, useEffect
sigue algunas reglas:
1. Llamar a hooks en la parte superior del componente: useEffect
y otros hooks deben ser llamados en la parte superior de un componente funcional, y nunca dentro de condicionales o bucles. Esto asegura que React mantenga el estado de los hooks correctamente.
2. No llamar a hooks dentro de funciones ordinarias: Los hooks deben ser utilizados exclusivamente en componentes funcionales o en custom hooks.
Antes de la introducción de hooks, los componentes de clase de React usaban métodos de ciclo de vida como componentDidMount
, componentDidUpdate
y componentWillUnmount
para manejar efectos secundarios. La introducción de useEffect
simplificó este proceso al combinar estas funcionalidades en un solo hook:
componentDidMount
y componentDidUpdate
→ useEffect
componentWillUnmount
→ Función de limpieza dentro de useEffect
useEffect
1. Evitar Dependencias Innecesarias: Asegúrate de definir correctamente el array de dependencias para evitar que el efecto se ejecute innecesariamente. React puede mostrar advertencias si las dependencias están mal definidas.
2. Memorización de funciones: Si pasas funciones al efecto, usa useCallback
para evitar crear nuevas instancias de la función en cada renderizado.
useEffect(() => {
const id = setInterval(() => {
setTime(new Date());
}, 1000);
return () => clearInterval(id);
}, []); // El array vacío asegura que el intervalo se configure solo una vez
En este ejemplo, setInterval
se configura una sola vez en el montaje, y clearInterval
limpia el intervalo en el desmontaje.
useEffect
es una herramienta poderosa para manejar efectos secundarios en los componentes funcionales de React. Comprender cómo y cuándo utilizar useEffect
es crucial para crear aplicaciones React eficientes y mantenibles. Al controlar correctamente el ciclo de vida de los efectos y definir las dependencias adecuadas, puedes crear aplicaciones reactivas y optimizadas sin las complejidades de los componentes de clase.
Jorge García
Fullstack developer