Lei vai due soluzioni!
1. Modifica ChangeDetectionStrategy su OnPush
Per questa soluzione, in pratica dirai angolare:
Smettere di controllare le modifiche; lo farò solo quando so che è necessario
La soluzione rapida:
Modifica il componente in modo che possa essere utilizzato ChangeDetectionStrategy.OnPush
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildComponent implements OnInit {
// ...
}
Con questo, le cose sembrano non funzionare più. Questo perché d'ora in poi dovrai fare in modo che Angular chiami detectChanges()
manualmente.
this.cdr.detectChanges();
Ecco un link che mi ha aiutato a capire bene ChangeDetectionStrategy :
https://alligator.io/angular/change-detection-strategy/
2. Comprensione di ExpressionChangedAfterItHasBeenCheckedError
Ecco un piccolo estratto dalla risposta di tomonari_t sulle cause di questo errore, ho provato a includere solo le parti che mi hanno aiutato a capirlo.
L'articolo completo mostra esempi di codice reali su ogni punto mostrato qui.
La causa principale è il ciclo di vita angolare:
Dopo ogni operazione Angolare ricorda quali valori ha usato per eseguire un'operazione. Sono memorizzati nella proprietà oldValues della vista componenti.
Dopo aver eseguito i controlli per tutti i componenti Angolare avvia quindi il successivo ciclo di digest ma invece di eseguire le operazioni confronta i valori correnti con quelli che ricorda del precedente ciclo di digest.
Le seguenti operazioni sono in fase di controllo presso il ciclo digest:
verificare che i valori passati ai componenti figlio siano gli stessi dei valori che ora verrebbero utilizzati per aggiornare le proprietà di questi componenti.
verifica che i valori utilizzati per aggiornare gli elementi DOM siano gli stessi dei valori che verrebbero utilizzati per aggiornare questi elementi ora eseguono lo stesso.
controlla tutti i componenti figlio
Quindi, l'errore viene generato quando i valori confrontati sono diversi. , il blogger Max Koretskyi ha dichiarato:
Il colpevole è sempre il componente figlio o una direttiva.
E finalmente ecco alcuni esempi del mondo reale che di solito causano questo errore:
- Servizi condivisi
- Trasmissione di eventi sincroni
- Istanziazione dinamica dei componenti
Ogni campione può essere trovato qui (plunkr), nel mio caso il problema era un'istanza di componente dinamica.
Inoltre, per mia esperienza, consiglio vivamente a tutti di evitare la setTimeout
soluzione, nel mio caso ha causato un ciclo "quasi" infinito (21 chiamate che non sono disposto a mostrarti come provocarle),
Consiglio di tenere sempre presente il ciclo di vita angolare in modo da poter tenere conto di come sarebbero interessati ogni volta che si modifica il valore di un altro componente. Con questo errore Angular ti sta dicendo:
Forse lo stai facendo nel modo sbagliato, sei sicuro di avere ragione?
Lo stesso blog dice anche:
Spesso, la soluzione consiste nell'utilizzare il giusto hook di rilevamento delle modifiche per creare un componente dinamico
Una breve guida per me è quella di considerare almeno le seguenti due cose durante la codifica ( cercherò di completarlo nel tempo ):
- Evita invece di modificare i valori dei componenti principali dai suoi componenti figlio, invece: modificali dai suoi genitori.
- Quando si utilizzano
@Input
e le @Output
direttive si tenta di evitare di attivare le modifiche del ciclo di vita a meno che il componente non sia completamente inizializzato.
- Evita chiamate inutili
this.cdr.detectChanges();
perché possono innescare più errori, specialmente quando hai a che fare con molti dati dinamici
- Quando l'uso di
this.cdr.detectChanges();
è obbligatorio, assicurarsi che le variabili ( @Input, @Output, etc
) utilizzate siano riempite / inizializzate al gancio di rilevamento destro ( OnInit, OnChanges, AfterView, etc
)
- Se possibile, rimuovere anziché nascondere , ciò è correlato ai punti 3 e 4.
Anche
Se vuoi comprendere appieno Angular Life Hook ti consiglio di leggere la documentazione ufficiale qui: