Siempre que el efecto se desencadena innecesariamente, el rendimiento de tu app se ve afectado.

El truco

// ANTES
useEffect(() => {
  fetchData(id);
}, [user]);

// DESPUÉS
useEffect(() => {
  fetchData(id);
}, [id]);

Evita que useEffect dependa de variables que no cambian en su lógica interna. Asegúrate de que tus dependencias en el array de dependencias estén realmente relacionadas con el proceso que ocurre dentro del efecto. En el ejemplo, fetchData solo necesita id, no user.

Evitar el uso de funciones anónimas dentro de useEffect puede salvarte de renderizados innecesarios y problemas de rendimiento.

El truco

// ANTES
useEffect(() => {
  const handleResize = () => console.log(window.innerWidth);
  window.addEventListener('resize', handleResize);
  return () => window.removeEventListener('resize', handleResize);
}, []);

// DESPUÉS
const handleResize = () => console.log(window.innerWidth);
useEffect(() => {
  window.addEventListener('resize', handleResize);
  return () => window.removeEventListener('resize', handleResize);
}, []);

Mover la función afuera de useEffect evita que se defina de nuevo en cada render, mejorando el rendimiento y clarificando el código.

Evita efectos que se ejecutan en cada render independientemente de si los valores han cambiado.

El truco

// ANTES
useEffect(() => {
  calculateExpensiveValue(data);
});

// DESPUÉS
useEffect(() => {
  calculateExpensiveValue(data);
}, [data]);

Incluye un array de dependencias para que el efecto solo se ejecute cuando data cambie.

Tu código debe ser tan eficiente como tú, evita patrones que sobrecarguen tu app innecesariamente.