18-Ciclo de Vida de un Componente React
Ciclo de Vida de un Componente React
Fases del Ciclo de Vida:
1. Montaje (Mounting)
El componente se crea y se inserta en el DOM.
2. Actualización (Updating)
El componente se re-renderiza debido a cambios en props o estado.
3. Desmontaje (Unmounting)
El componente se elimina del DOM.
Diagrama Completo del Ciclo de Vida-En Componentes de Clase:
class MiComponente extends React.Component {
// 1. CONSTRUCTOR (montaje)
constructor(props) {
super(props);
this.state = { contador: 0 };
console.log('constructor');
} // 2. getDerivedStateFromProps (montaje/actualización)
static getDerivedStateFromProps(props, state) {
console.log('getDerivedStateFromProps');
return null; // Retorna nuevo estado o null
} // 3. RENDER (montaje/actualización)
render() {
console.log('render');
return <div>Contador: {this.state.contador}</div>;
}// 4. componentDidMount (montaje)
componentDidMount() {
console.log('componentDidMount');
// Aquí haces peticiones API, suscripciones, etc.
} // 5. shouldComponentUpdate (actualización)
shouldComponentUpdate(nextProps, nextState) {
console.log('shouldComponentUpdate');
return true; // true para re-renderizar, false para no hacerlo
}// 6. getSnapshotBeforeUpdate (actualización)
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log('getSnapshotBeforeUpdate');
return null; // Puede retornar un valor para componentDidUpdate
}
// 7. componentDidUpdate (actualización)
componentDidUpdate(prevProps, prevState, snapshot) {
console.log('componentDidUpdate');
// Aquí puedes hacer operaciones después del update
}
// 8. componentWillUnmount (desmontaje)
componentWillUnmount() {
console.log('componentWillUnmount');
// Aquí limpias suscripciones, temporizadores, etc.
}
}
En Componentes Funcionales (con Hooks):
javascript
import { useState, useEffect } from 'react';
function MiComponente() {
const [contador, setContador] = useState(0);
// Equivalente a componentDidMount + componentDidUpdate
useEffect(() => {
console.log('Efecto ejecutado (montaje/actualización)');
// Función de cleanup (equivalente a componentWillUnmount)
return () => {
console.log('Cleanup ejecutado');
};
}, [contador]); // Dependencias: se ejecuta cuando contador cambia
// useEffect sin dependencias = solo en montaje
useEffect(() => {
console.log('Solo en montaje (como componentDidMount)');
return () => {
console.log('Cleanup al desmontar');
};
}, []); // Array vacío = solo montaje/desmontaje
console.log('render');
return <div>Contador: {contador}</div>;
}
Cómo se Relaciona Todo:
1. Estado (State) → Virtual DOM → DOM Real
javascript
// Cuando el ESTADO cambia:
class Componente extends React.Component {
state = { valor: 0 };
handleClick = () => {
// 1. Cambio de estado
this.setState({ valor: 1 });
// 2. React marca el componente como "necesita actualización"
// 3. Se ejecuta shouldComponentUpdate()
// 4. Se ejecuta render() → crea NUEVO Virtual DOM
// 5. React compara Virtual DOM viejo vs nuevo (Diffing)
// 6. React calcula cambios mínimos necesarios
// 7. React aplica esos cambios al DOM REAL
// 8. Se ejecuta componentDidUpdate()
}
}
2. Enganchar/Desenganchar Componentes-¿Qué significa "enganchar"?
Significa conectar un componente al árbol de componentes de React y al DOM.
javascript
// Cuando un componente se "engancha":
// 1. Se crea la instancia
// 2. Se inicializa el estado
// 3. Se renderiza por primera vez
// 4. Se inserta en el DOM
// 5. Se ejecutan efectos (useEffect o componentDidMount)
// Ejemplo de enganche con useEffect:
useEffect(() => {
// Esto se ejecuta cuando el componente se ENGANCHA
const suscripcion = API.suscribir();
return () => {
// Esto se ejecuta cuando el componente se DESENGANCHA
suscripcion.cancelar();
};
}, []);
Ejemplo Práctico: Suscripción a Datos
function ChatComponent() {
const [mensajes, setMensajes] = useState([]);
useEffect(() => {
// ENGANCHAR: Cuando el componente se monta
console.log('🔌 Conectando al servidor de chat...');
const socket = conectarSocket();
// Escuchar mensajes nuevos
socket.on('nuevoMensaje', (mensaje) => {
setMensajes(prev => [...prev, mensaje]);
});
// DESENGANCHAR: Cuando el componente se desmonta
return () => {
console.log('🔌 Desconectando del servidor...');
socket.desconectar(); // Limpieza
};
}, []); // [] = solo en montaje/desmontaje
return <div>Chat: {mensajes.length} mensajes</div>;}
Flujo Completo con Todos los Conceptos Escenario: Componente de Contador
// 1. DECLARACIÓN DEL COMPONENTE
function Contador({ inicial = 0 }) {
// 2. ESTADO (memoria interna del componente)
const [contador, setContador] = useState(inicial);
// 3. EFECTOS (ciclo de vida)
useEffect(() => {
// FASE DE MONTAJE (enganche)
console.log('✅ Componente MONTADO en el DOM');
document.title = `Contador: ${contador}`;
return () => {
// FASE DE DESMONTAJE (desenganche)
console.log('❌ Componente DESMONTADO del DOM');
document.title = 'React App'; // Restaurar título
};
}, []); // Solo en montaje/desmontaje
useEffect(() => {
// FASE DE ACTUALIZACIÓN
console.log('🔄 Contador actualizado:', contador);
}, [contador]); // Solo cuando contador cambia
// 4. RENDER (crea Virtual DOM)
console.log('🎨 Renderizando Virtual DOM...');
return (
<div>
<p>Valor: {contador}</p>
<button onClick={() => setContador(c => c + 1)}>
Incrementar
</button>
</div>
);
}// 5. USO DEL COMPONENTE
function App() {
const [mostrar, setMostrar] = useState(true);
return (
<div>
<button onClick={() => setMostrar(!mostrar)}>
{mostrar ? 'Ocultar' : 'Mostrar'} Contador
</button>
{/* Cuando 'mostrar' es true, el componente se ENGANCHA */}
{/* Cuando 'mostrar' es false, el componente se DESENGANCHA */}
{mostrar && <Contador inicial={5} />}
</div> );}
Secuencia de Eventos:
Al hacer clic en "Mostrar Contador":
text
1. React crea el componente Contador
2. useState() inicializa el estado (contador = 5)
3. Console: "🎨 Renderizando Virtual DOM..."
4. React crea elemento Virtual DOM
5. React compara con DOM anterior
6. React inserta el div en DOM real
7. useEffect() se ejecuta: "✅ Componente MONTADO"
Al hacer clic en "Incrementar":
text
1. setContador() actualiza el estado
2. React marca componente para re-render
3. Console: "🎨 Renderizando Virtual DOM..."
4. React crea NUEVO Virtual DOM con contador = 6
5. React COMPARA con Virtual DOM anterior
6. React detecta que solo cambió el texto "Valor: 5" → "Valor: 6"
7. React ACTUALIZA solo ese texto en el DOM real
8. Console: "🔄 Contador actualizado: 6"
Al hacer clic en "Ocultar Contador":
text
1. React prepara desmontaje
2. Ejecuta cleanup de useEffect: "❌ Componente DESMONTADO"
3. React elimina el elemento del DOM real
4. Estado del componente se pierde (a menos que esté elevado)
Relaciones Clave:
Estado ↔ Virtual DOM
El estado determina QUÉ se renderiza
Cambios en estado → Nuevo Virtual DOM → Actualización DOM real
Ciclo de Vida ↔ DOM Virtual
Montaje: Virtual DOM → DOM real
Actualización: Virtual DOM anterior vs nuevo → Cambios mínimos
Desmontaje: Eliminar del DOM real
Enganchar/Desenganchar ↔ Efectos
Enganchar = Montar + Configurar recursos
Desenganchar = Desmontar + Limpiar recursos
Buenas Prácticas:
1. Limpieza en Desmontaje:
javascript
useEffect(() => {
const intervalo = setInterval(() => {}, 1000);
const suscripcion = api.suscribir();
return () => {
clearInterval(intervalo); // 🔴 IMPORTANTE!
suscripcion.cancelar(); // Evitar memory leaks
};
}, []);
2. Actualizaciones Optimizadas:
javascript
// ❌ Mal: Re-render en cada actualización
useEffect(() => {
console.log('Se ejecuta siempre');
}); // Sin array de dependencias
// ✅ Bien: Solo cuando 'data' cambia
useEffect(() => {
console.log('Solo cuando data cambia');
}, [data]); // Con dependencias específicas
3. Manejo de Suscripciones:
javascript
function UsuarioEnVivo({ usuarioId }) {
const [estaEnLinea, setEstaEnLinea] = useState(null);
useEffect(() => {
// Enganchar suscripción
const unsubscribe = firebase
.suscribirEstadoUsuario(usuarioId, (estado) => {
setEstaEnLinea(estado);
});
// Desenganchar suscripción
return () => unsubscribe();
}, [usuarioId]); // Se re-engancha si usuarioId cambia
return <div>Usuario {estaEnLinea ? 'en línea' : 'offline'}</div>;
}
Resumen Visual:
text
[Estado/Props Cambian]
↓
[Componente Re-renderiza]
↓
[Nuevo Virtual DOM Creado]
↓
[React Compara con Anterior]
↓
[Cálculo de Cambios Mínimos]
↓
[Aplicación al DOM Real]
↓
[Efectos (DidMount/DidUpdate)]
↓
[Espera Nuevos Cambios...]
↑
└─────────┐
↓
[Usuario Interactúa]
↓
[setState() Llamado]
El ciclo de vida, estado, Virtual DOM y hooks están íntimamente conectados: El estado dicta el renderizado, el Virtual DOM optimiza las actualizaciones, y los hooks te permiten "enganchar" código en puntos específicos del ciclo de vida para crear componentes interactivos y eficientes.
Comentarios
Publicar un comentario