Every Angular component moves through a predictable set of lifecycle stages, from creation to destruction. This lesson covers each lifecycle hook, in the order Angular calls them, with practical examples.
What Is the Component Lifecycle?
Angular manages the full lifecycle of every component instance: creating it, checking and updating its inputs, rendering its view, responding to changes, and eventually destroying it when it's removed from the DOM. Lifecycle hooks are methods you implement to run code at specific points in that process.
Hooks are optional, implement only the ones you actually need. The two most commonly used are ngOnInit (setup logic) and ngOnDestroy (cleanup logic).
ngOnInit starts the timer once the component is initialized; ngOnDestroy clears it to avoid leaking a running interval.
Lifecycle Hook Order
constructor()
ngOnChanges() // before ngOnInit, and on every input change
ngOnInit() // once, after the first ngOnChanges
ngDoCheck() // on every change detection run
ngAfterContentInit()
ngAfterContentChecked()
ngAfterViewInit()
ngAfterViewChecked()
ngOnDestroy() // once, just before Angular destroys the component
Implement a hook by adding its corresponding interface (OnInit, OnDestroy, etc.) and method to your class.
ngOnChanges runs before ngOnInit and again whenever a bound @Input() changes.
ngAfterViewInit is the first point where child component views and @ViewChild references are guaranteed available.
ngOnDestroy is your one chance to clean up subscriptions, timers, and listeners before the component is removed.
Lifecycle Hooks Cheatsheet
When each hook runs and what it's typically used for.
Hook
Runs When
Typical Use
ngOnChanges
An @Input() value changes
React to new input values
ngOnInit
Once, after the first input check
Initial data fetch, setup
ngDoCheck
Every change detection run
Custom, manual change detection
ngAfterContentInit
Once, after projected content is initialized
Work with @ContentChild
ngAfterContentChecked
After every content check
React to projected content changes
ngAfterViewInit
Once, after the view (and children) is initialized
Work with @ViewChild
ngAfterViewChecked
After every view check
React to view changes (use sparingly)
ngOnDestroy
Just before the component is destroyed
Unsubscribe, clear timers/listeners
ngOnInit vs the Constructor
The constructor is plain TypeScript/JavaScript and runs before Angular has set any @Input() values or initialized the component's dependency injection context fully for view-related work. ngOnInit runs after Angular has processed the first round of inputs, making it the right place for setup logic that depends on those inputs.
Use the constructor only for simple dependency injection (private http = inject(HttpClient)).
Use ngOnInit for initial API calls, subscriptions, or setup logic depending on @Input() values.
Avoid heavy logic in the constructor, it can make components harder to test and instantiate.
Reacting to Input Changes With ngOnChanges
ngOnChanges receives a SimpleChanges object describing which inputs changed, along with their previous and current values, useful when a component needs to respond specifically to an input update rather than just reading the latest value.
Anything a component sets up that outlives a single render, subscriptions, setInterval/setTimeout timers, or manually attached event listeners, must be cleaned up in ngOnDestroy, otherwise it keeps running (and potentially leaking memory) after the component is gone.
Doing initial data fetching in the constructor instead of ngOnInit.
Forgetting to unsubscribe from Observables in ngOnDestroy, causing memory leaks and stale updates.
Reading @ViewChild references before ngAfterViewInit has run, when they are still undefined.
Overusing ngDoCheck/ngAfterViewChecked for logic that runs on every single change detection cycle, hurting performance.
Key Takeaways
Angular calls lifecycle hooks in a fixed order: changes, init, content, view, and eventually destroy.
ngOnInit is the standard place for setup logic that depends on component inputs.
ngOnDestroy is essential for cleaning up subscriptions, timers, and listeners.
ngAfterViewInit is the first safe point to read @ViewChild references.
Pro Tip
For components using signals exclusively, consider effect() for reactive side effects rather than manually orchestrating logic across multiple lifecycle hooks, it can simplify code that reacts to changing state.
You now understand the Angular component lifecycle. Next, learn about @Input and @Output to pass data and events between parent and child components.