Las aplicaciones de React se construyen a partir de componentes, y cada componente tiene una vida. Aparece en la pantalla. Reacciona a nueva información. Finalmente, desaparece. Ignora ese ritmo y el precio será real. Se filtran fugas de memoria. El rendimiento del renderizado se degrada. Los usuarios hacen clic en botones que ya no responden porque el componente vinculado a ellos se desmontó hace diez minutos, pero el escuchador de eventos sigue vivo. Comprender el ciclo de vida de los componentes no es un ejercicio académico. Es la base para escribir software que se mantenga confiable bajo un uso real.

Piensa en la existencia de un componente en tres etapas. Los desarrolladores suelen describirlas como nacimiento, crecimiento y muerte. React las llama mounting, updating y unmounting. Cada etapa tiene un trabajo específico, y cada una te ofrece un momento preciso para ejecutar código o realizar una limpieza.

Las tres fases

Mounting es el nacimiento. El componente se crea y se inserta en el DOM del navegador por primera vez. Esta es tu ventana de configuración. Si el componente necesita datos remotos, este es el momento de solicitarlos. Si necesita un estado inicial calculado a partir de props, lo haces aquí. En la era de los componentes de clase, este era el dominio de componentDidMount. Con los componentes funcionales modernos, lo gestionas con useEffect y un array de dependencias vacío. El detalle clave es que este bloque de código se ejecuta una sola vez, inmediatamente después de que React coloca el elemento en la página. Eso lo hace ideal para configuraciones únicas, como obtener un perfil de usuario o leer un valor de localStorage.

Updating es el crecimiento. Un componente montado no se queda quieto. Llegan props de un padre. El estado cambia debido a una interacción del usuario. El propio padre se vuelve a renderizar, obligando al hijo a hacer lo mismo. React vuelve a renderizar el componente para mantener la interfaz de usuario sincronizada con tus datos. Esta fase se repite muchas veces durante la vida de un componente. Cada vez que una dependencia cambia, tus efectos se ejecutan de nuevo y el componente devuelve una nueva salida al DOM. Debido a que esta fase se activa con tanta frecuencia, también es donde comienzan la mayoría de los problemas de rendimiento. El trabajo innecesario aquí se acumula rápidamente.

Unmounting es la muerte. El componente sale de la pantalla, tal vez porque el usuario navegó a una página diferente o un renderizado condicional se desactivó. En este punto, el componente se destruye, pero el mundo exterior no siempre lo sabe. Los temporizadores siguen corriendo. Los WebSockets siguen escuchando. Los event listeners en el objeto window permanecen conectados. Si no realizas una limpieza, estos mantienen referencias a componentes muertos y provocan fugas de memoria. El navegador desperdicia ciclos en fantasmas. React te proporciona una función de limpieza precisamente para que puedas detener intervalos, cerrar conexiones y eliminar escuchadores antes de que el componente desaparezca para siempre.

De los métodos de clase a los Hooks

Durante años, los ingenieros de React gestionaron estas fases a través de componentes de clase. La lógica se dividía en distintos métodos. Obtenías datos dentro de componentDidMount, respondías a los cambios de props dentro de componentDidUpdate y "barrías el suelo" dentro de componentWillUnmount. El problema era que la lógica relacionada terminaba dispersa. Una sola funcionalidad, como una conexión de chat en vivo, requería código en tres métodos de ciclo de vida distintos solo para conectar, verificar cambios en el hilo y desconectar.

Los Hooks cambiaron eso. El hook useEffect en componentes funcionales te permite agrupar la lógica por propósito en lugar de por fase de ciclo de vida. Aun así, el modelo mental se mapea claramente si sabes dónde buscar.

Para manejar el mounting, escribe useEffect(() => { ... }, []). El array de dependencias vacío le indica a React que este efecto no tiene dependencias externas, por lo que se ejecuta solo después del renderizado inicial. Esto reemplaza a componentDidMount.

Para manejar las actualizaciones, incluye los valores específicos que React debe observar: useEffect(() => { ... }, [dependency]). Cuando dependency cambia entre renderizados,