Cuando un componente tiene OnPush, solo se actualizará si ocurre alguna de estas situaciones:
1️⃣ Cambio en un @Input()
Si el valor del @Input()
cambia de referencia, Angular actualizará el componente.
✅ Se actualiza porque cambia la referencia (objeto nuevo)
this.producto = { nombre: 'Nuevo Producto' };
// Esto genera una nueva referencia en memoria
❌ No se actualiza si solo se modifica una propiedad interna
this.producto.nombre = 'Nuevo Producto';
// No cambia la referencia del objeto en memoria, Angular no lo detecta
💡 Solución: Para forzar la detección de cambios, asigna un nuevo objeto:
this.producto = { ...this.producto, nombre: 'Nuevo Producto' };
2️⃣ Eventos del DOM (click, input, etc.)
Si el componente tiene un evento como (click)
, (input)
, (change)
, etc., Angular detectará el cambio.
(click)="cambiarValor()">Actualizar
cambiarValor() {
this.valor = 'Nuevo';
}
Esto siempre actualizará la vista, incluso con OnPush
.
3️⃣ Uso de async
en un | async
pipe (Observables)
Si usas el pipe async
, Angular actualizará automáticamente el componente cuando el Observable emita un nuevo valor.
{{ datos$ | async }}
datos$ = this.http.get('https://api.example.com/data');
4️⃣ Cambios manuales con markForCheck()
Si necesitas actualizar manualmente el componente, puedes usar ChangeDetectorRef.markForCheck()
.
constructor(private cd: ChangeDetectorRef) {}
actualizar() {
this.valor = 'Nuevo';
this.cd.markForCheck(); // 🔥 Forzar actualización
}
5️⃣ Cambio en una variable dentro de un setTimeout
o setInterval
Si modificamos una variable dentro de setTimeout
, Angular no lo detectará a menos que usemos markForCheck()
.
❌ No se actualiza automáticamente
setTimeout(() => {
this.valor = 'Nuevo';
}, 2000);
✅ Solución con markForCheck()
setTimeout(() => {
this.valor = 'Nuevo';
this.cd.markForCheck();
}, 2000);
6️⃣ Cambios después de una petición HTTP manual
Si asignamos un nuevo valor después de una petición HTTP sin async
, Angular no lo detectará automáticamente.
❌ No se actualiza automáticamente
this.http.get('https://api.example.com/data').subscribe(data => {
this.valor = data;
});
✅ Solución con markForCheck()
this.http.get('https://api.example.com/data').subscribe(data => {
this.valor = data;
this.cd.markForCheck();
});
7️⃣ Re-adjuntar la detección de cambios con reattach()
Si en algún momento se desactiva la detección de cambios con cd.detach()
, podemos volver a activarla con reattach()
.
this.cd.detach(); // 🛑 Detiene la detección
this.cd.reattach(); // 🔄 Reactiva la detección
📌 Resumen final
Si un componente tiene OnPush
, solo se actualizará cuando ocurra alguno de estos eventos:
Evento | ¿Actualiza con OnPush ? |
---|---|
Cambio en un @Input() (nueva referencia) |
✅ Sí |
Evento del DOM (click , input , etc.) |
✅ Sí |
async pipe con Observables |
✅ Sí |
Uso de markForCheck()
|
✅ Sí |
setTimeout o setInterval
|
❌ No (a menos que uses markForCheck() ) |
HTTP Request (subscribe() ) |
❌ No (a menos que uses markForCheck() ) |
detach() |
❌ No |
reattach() |
✅ Sí |
🎯 Conclusión
🔹 OnPush
mejora el rendimiento porque evita que Angular revise el componente en cada ciclo de cambio.
🔹 Sin embargo, sigue actualizándose en situaciones clave como cambios en @Input
, eventos del DOM o usando markForCheck()
.
🔹 Si necesitas forzar un cambio manualmente, usa markForCheck()
o detectChanges()
.
Ahora tienes el conocimiento completo sobre OnPush
y cuándo se actualizan los componentes. 🚀🔥