DEV Community

Cristian Arieta
Cristian Arieta

Posted on

🔥 ¿Cuándo se actualiza un componente con `OnPush`?

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

💡 Solución: Para forzar la detección de cambios, asigna un nuevo objeto:

this.producto = { ...this.producto, nombre: 'Nuevo Producto' };
Enter fullscreen mode Exit fullscreen mode

2️⃣ Eventos del DOM (click, input, etc.)

Si el componente tiene un evento como (click), (input), (change), etc., Angular detectará el cambio.

<button (click)="cambiarValor()">Actualizar</button>
Enter fullscreen mode Exit fullscreen mode
cambiarValor() {
  this.valor = 'Nuevo';
}
Enter fullscreen mode Exit fullscreen mode

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.

<p>{{ datos$ | async }}</p>
Enter fullscreen mode Exit fullscreen mode
datos$ = this.http.get('https://api.example.com/data');
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

Solución con markForCheck()

setTimeout(() => {
  this.valor = 'Nuevo';
  this.cd.markForCheck();
}, 2000);
Enter fullscreen mode Exit fullscreen mode

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;
});
Enter fullscreen mode Exit fullscreen mode

Solución con markForCheck()

this.http.get('https://api.example.com/data').subscribe(data => {
  this.valor = data;
  this.cd.markForCheck();
});
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

📌 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. 🚀🔥

Top comments (0)