Ella te va dos soluciones!
1. Modificar ChangeDetectionStrategy a OnPush
Para esta solución, básicamente le estás diciendo a angular:
Dejar de buscar cambios; lo haré solo cuando sepa que es necesario
La solución rápida:
Modifique su componente para que use ChangeDetectionStrategy.OnPush
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildComponent implements OnInit {
// ...
}
Con esto, las cosas ya no parecen funcionar. Eso es porque a partir de ahora tendrás que hacer que Angular llame detectChanges()
manualmente.
this.cdr.detectChanges();
Aquí hay un enlace que me ayudó a entender ChangeDetectionStrategy a la derecha:
https://alligator.io/angular/change-detection-strategy/
2. Comprender ExpressionChangedAfterItHasBeenCheckedError
Aquí hay un pequeño extracto de la respuesta de tomonari_t sobre las causas de este error. Intenté incluir solo las partes que me ayudaron a entender esto.
El artículo completo muestra ejemplos de código real sobre cada punto que se muestra aquí.
La causa raíz es el ciclo de vida angular:
Después de cada operación, Angular recuerda qué valores utilizó para realizar una operación. Se almacenan en la propiedad oldValues de la vista de componentes.
Después de que se hayan realizado las comprobaciones de todos los componentes, Angular inicia el siguiente ciclo de resumen, pero en lugar de realizar operaciones, compara los valores actuales con los que recuerda del ciclo de resumen anterior.
Las siguientes operaciones se verifican en el ciclo de resumen:
compruebe que los valores transmitidos a los componentes secundarios son los mismos que los valores que se usarían para actualizar las propiedades de estos componentes ahora.
compruebe que los valores utilizados para actualizar los elementos DOM son los mismos que los valores que se usarían para actualizar estos elementos ahora realizan lo mismo.
comprueba todos los componentes secundarios
Y así, el error se produce cuando los valores comparados son diferentes. , el blogger Max Koretskyi declaró:
El culpable es siempre el componente hijo o una directiva.
Y finalmente, aquí hay algunas muestras del mundo real que generalmente causan este error:
- Servicios compartidos
- Difusión de eventos síncronos
- Instanciación dinámica de componentes
Cada muestra se puede encontrar aquí (plunkr), en mi caso el problema era una instanciación dinámica de componentes.
Además, según mi propia experiencia, recomiendo encarecidamente a todos que eviten la setTimeout
solución, en mi caso causó un bucle "casi" infinito (21 llamadas que no estoy dispuesto a mostrarle cómo provocarlas),
Recomendaría tener siempre en cuenta el ciclo de vida angular para que pueda tener en cuenta cómo se verían afectados cada vez que modifique el valor de otro componente. Con este error, Angular te dice:
Tal vez estás haciendo esto de la manera incorrecta, ¿estás seguro de que tienes razón?
El mismo blog también dice:
A menudo, la solución es usar el gancho de detección de cambio correcto para crear un componente dinámico
Una breve guía para mí es considerar al menos las siguientes dos cosas al codificar ( intentaré complementarlo con el tiempo ):
- Evite modificar los valores de los componentes primarios a partir de los componentes de su hijo, en su lugar: modifíquelos desde su padre.
- Cuando utilice
@Input
y las @Output
directivas, trate de evitar desencadenar cambios en lyfecycle a menos que el componente esté completamente inicializado.
- Evite llamadas innecesarias, ya
this.cdr.detectChanges();
que pueden provocar más errores, especialmente cuando se trata de una gran cantidad de datos dinámicos.
- Cuando el uso de
this.cdr.detectChanges();
es obligatorio, asegúrese de que las variables ( @Input, @Output, etc
) que se utilizan estén llenas / inicializadas en el gancho de detección correcto ( OnInit, OnChanges, AfterView, etc
)
- Cuando sea posible, eliminar en lugar de ocultar , esto está relacionado con los puntos 3 y 4.
también
Si desea comprender completamente Angular Life Hook, le recomiendo que lea la documentación oficial aquí: