Panel szczegółów dostaje nowe id, ale nadal pokazuje poprzedni rekord, bo kod reaguje tylko przy tworzeniu komponentu. Najczęściej trzeba wtedy obsłużyć ngOnChanges, choć właściwy moment zależy od tego, czy problem dotyczy wejścia, widoku, czy sprzątania po komponencie.
Hook dobierz do chwili, w której Angular udostępnia potrzebne dane
ngOnChangesreaguje na zmiany wejść i przy pierwszej inicjalizacji działa przedngOnInit.ngOnInituruchamia się raz, gdy Angular ustawi wejścia komponentu.ngAfterViewInitpozwala odczytać zapytania do widoku, ale zmiana stanu powiązanego z szablonem może wywołać błąd NG0100.ngOnDestroy,DestroyRefitakeUntilDestroyedpomagają kończyć pracę komponentu i jego subskrypcji.afterNextRendersłuży do kodu po renderowaniu DOM w przeglądarce; nie uruchamia się podczas renderowania po stronie serwera.

ngOnChanges wyprzedza ngOnInit i reaguje na kolejne wejścia
Komponent potomny może powstać raz, a dostać kilka różnych wartości wejściowych. Właśnie dlatego ngOnInit nie wystarczy, gdy trzeba ponownie zareagować na zmianę danych przekazanych przez rodzica.
Podczas pierwszego sprawdzenia Angular wywołuje ngOnChanges, jeśli zmieniły się wejścia, a potem ngOnInit. Kolejne zmiany wejść ponownie uruchamiają ngOnChanges. Metoda otrzymuje obiekt SimpleChanges, w którym dla zmienionego pola znajdziesz poprzednią i bieżącą wartość oraz informację, czy to pierwsza zmiana.
export class DetailsComponent implements OnChanges {
@Input() recordId = '';
ngOnChanges(changes: SimpleChanges): void {
const change = changes['recordId'];
if (change) {
this.loadRecord(change.currentValue);
}
}
}
Jeśli recordId zmienia się po nawigacji między rekordami, pobranie danych w ngOnInit wykonałoby się tylko przy pierwszym utworzeniu komponentu. Obsługa zmiany wejścia trafia do ngOnChanges; konfiguracja potrzebna tylko raz może pozostać w ngOnInit. Dokumentacja Angulara wskazuje też, że przy aliasie wejścia kluczem w SimpleChanges pozostaje nazwa właściwości w klasie.
NG0100 często oznacza zmianę stanu po sprawdzeniu widoku
Odczyt referencji do elementu i zmiana wartości wyświetlanej w szablonie to dwie różne operacje. ngAfterViewInit pozwala odczytać zapytania do widoku po jego inicjalizacji, ale zmiana w tym miejscu wartości powiązanej z szablonem może skończyć się błędem ExpressionChangedAfterItHasBeenCheckedError (NG0100).
Popularna rada, by przenieść problematyczny kod do innego hooka „po widoku”, nie zawsze rozwiązuje przyczynę. W dokumentacji Angulara błąd NG0100 wiąże się ze zmianą wyrażenia po zakończeniu sprawdzania. W trybie deweloperskim framework wykonuje dodatkową kontrolę, która wykrywa niestabilny widok. Jeśli inicjalizujesz stan, zacznij od ngOnInit; jeśli potrzebujesz jedynie odczytać element widoku, użyj ngAfterViewInit bez modyfikowania stanu, od którego zależy bieżący szablon.
| Sytuacja | Prawdopodobna przyczyna | Co zrobić |
|---|---|---|
Widok zmienia się po przypisaniu wartości w ngAfterViewInit |
Powiązanie szablonu zmieniło się po sprawdzeniu widoku | Ustaw początkowy stan wcześniej albo oddziel odczyt referencji od zmiany danych szablonu |
| Po zmianie parametru rodzica zostaje poprzedni rekord | Logika działa tylko w ngOnInit |
Reaguj na zmienione wejście w ngOnChanges |
| W konsoli pojawiają się skutki pracy po usunięciu komponentu | Subskrypcja lub inny zasób nadal działa | Zakończ go przy niszczeniu komponentu, na przykład przez takeUntilDestroyed |
| Kod dotykający DOM działa w przeglądarce, ale nie przy renderowaniu serwerowym | Callback renderowania nie uruchamia się na serwerze | Nie zakładaj dostępności DOM w kodzie SSR; przenieś operację do ścieżki wykonywanej w przeglądarce |
W tym rozróżnieniu stawiam na moment, w którym dane są rzeczywiście gotowe, zamiast na nazwę hooka, która „brzmi jak właściwa”. To zwykle prowadzi do prostszej naprawy niż wymuszanie kolejnego sprawdzenia widoku.
Do DOM użyj callbacku renderowania, a ciężkie hooki zostaw w spokoju
Metody ngDoCheck, ngAfterContentChecked i ngAfterViewChecked mogą uruchamiać się przy kolejnych przebiegach sprawdzania zmian. Wkładanie do nich kosztownej pracy albo zapisu stanu potrafi obciążyć wiele komponentów naraz, więc sięgam po nie tylko wtedy, gdy standardowe śledzenie zmian nie wystarcza.
Gdy zadanie wymaga pracy z DOM po renderowaniu, nowsze API Angulara udostępnia afterNextRender i afterEveryRender. Rejestruje się je w kontekście wstrzykiwania, na przykład w konstruktorze; callbacki dotyczą renderowania aplikacji, a nie wyłącznie pojedynczej instancji komponentu. Przy afterNextRender praca z DOM może poczekać do następnego renderu, natomiast afterEveryRender uruchamia się po każdym renderze, więc łatwo wykonać niepotrzebnie powtarzalną pracę.
Gdy operacja ma odczytać wymiary, wybieram fazę read; gdy ma zmienić DOM, fazę write. Dokumentacja API Angulara zaleca rozdzielać odczyty i zapisy, gdy to możliwe, bo ich mieszanie może pogorszyć wydajność. Render callbacks nie działają podczas renderowania serwerowego ani prerenderowania, dlatego kod wymagający przeglądarkowego DOM musi uwzględniać ten warunek.
Sprzątanie zacznij tam, gdzie kończy się życie komponentu
Komponent może zniknąć po zmianie trasy albo po wyłączeniu go przez @if. Jeśli uruchomił subskrypcję, timer lub nasłuchiwanie zdarzeń, powinien też zadbać o ich zakończenie. ngOnDestroy jest standardowym miejscem na takie porządki.
W kodzie opartym na RxJS operator takeUntilDestroyed z pakietu @angular/core/rxjs-interop kończy subskrypcję wraz z niszczeniem komponentu lub dyrektywy. Przy innych zasobach można użyć DestroyRef i zarejestrować funkcję porządkową blisko miejsca, w którym zasób powstaje. Takie zestawienie ułatwia ocenę, czy komponent zwalnia wszystko, co sam uruchomił.
Wybór można sprowadzić do prostego warunku: zmienia się wejście - reaguj w ngOnChanges; inicjalizujesz stan raz - użyj ngOnInit; czytasz widok - poczekaj na ngAfterViewInit; dotykasz DOM po renderze - rozważ callback renderowania; kończysz pracę - użyj ngOnDestroy lub DestroyRef.
Dobry hook wynika z tego, co komponent właśnie robi
Przy diagnozie zacznij od rodzaju pracy, nie od pełnej listy metod. Zmiana wejścia, inicjalizacja, dostęp do widoku, manipulacja DOM i sprzątanie dzieją się w różnych momentach, a właściwy hook ogranicza ryzyko starego stanu, błędu NG0100 albo wiszącej subskrypcji.
Jeśli używasz wejść opartych na sygnałach, część reakcji na zmiany można wyrazić przez sygnały obliczane lub efekty; klasyczne hooki nadal przydają się tam, gdzie ich cykl wykonania pasuje do zadania. Najpierw ustal, kiedy potrzebne dane są dostępne i kiedy komponent przestaje istnieć. Dopiero potem wybierz metodę, która w tym momencie daje najczytelniejszy kod.
