This lesson consolidates the most impactful mistakes covered throughout this course into a single, explanation-focused reference, useful both for learning and for debugging unfamiliar Angular code.
Why the Same Mistakes Keep Recurring
Many Angular mistakes share a root cause: forgetting that a particular API is asynchronous (Observables, HTTP), forgetting that OnPush/signals compare by reference, or forgetting a cleanup step (unsubscribing, destroying dynamic components). Recognizing the pattern behind a mistake makes it much easier to avoid the next one.
This lesson groups common mistakes by root cause rather than by feature, so the underlying lesson transfers to situations not explicitly listed here.
// Common root cause: forgetting Observables are lazy
getUsers() {
this.userService.getUsers(); // WRONG: never subscribed, nothing happens
}
// Fix
getUsers() {
this.userService.getUsers().subscribe(users => this.users = users);
}
This single misunderstanding, that Observables do nothing until subscribed, explains a large share of "my data never loads" bugs.
Root Causes Behind Common Mistakes
1. Forgetting Observables are lazy (never subscribed)
2. Forgetting OnPush/signals compare by reference (mutating in place)
3. Forgetting to clean up (subscriptions, timers, dynamic components)
4. Misunderstanding scope (DI, route parameters, module boundaries)
Most "nothing happens" bugs trace back to a missing .subscribe() or missing async pipe.
Most "my view won't update" bugs trace back to mutating data in place instead of replacing references.
Most memory-leak-style bugs trace back to a missing cleanup step in ngOnDestroy or missing takeUntilDestroyed().
Most "why doesn't my service see the same data" bugs trace back to a DI scoping misunderstanding.
Common Mistakes Cheatsheet
Frequent mistakes, grouped by the underlying misunderstanding.
Mistake
Root Cause
Fix
Data never appears after an API call
Forgot to .subscribe()
Subscribe or use the async pipe
OnPush component doesn't update
Mutated an object/array in place
Replace with a new object/array reference
Stale subscription updates a destroyed component
Missing cleanup
Use takeUntilDestroyed() or manual unsubscribe()
"No provider found" DI error
Service not provided in a reachable injector
Check providedIn/providers scoping
Route param read once, never updates
Used snapshot instead of the Observable form
Subscribe to paramMap or use component input binding
Search box fires excessive requests
No debouncing/cancellation
Add debounceTime + switchMap
*ngIf/@if shows stale data briefly
No loading state modeled
Track loading/error/data explicitly
Async-Related Mistakes
Because so much of Angular is Observable-based, misunderstanding when and how Observables actually execute is one of the single biggest sources of confusing bugs for newcomers.
Assuming an HttpClient call happens just by referencing it, without subscribing.
Subscribing multiple times to the same Observable in a template instead of aliasing with as.
Using switchMap where a sequential concatMap was actually needed (or vice versa).
Change-Detection-Related Mistakes
OnPush and signals both depend on reference-based change detection, mutating data in place silently breaks this assumption without throwing any error.
Mutating an array/object bound to an OnPush component instead of replacing the reference.
Forgetting markForCheck() when updating state from outside Angular's normal event flow.
Reading a signal without calling it as a function (missing the parentheses).
Cleanup-Related Mistakes
Anything that outlives a single render (subscriptions, timers, dynamically created components) needs an explicit cleanup step, or it keeps running after it should have stopped.
Not unsubscribing from long-lived Observables in ngOnDestroy.
Not calling componentRef.destroy() on dynamically created components.
Leaving setInterval/setTimeout timers running past a component's lifetime.
Common Mistakes
Memorizing individual "gotchas" without understanding the underlying pattern they share.
Assuming a mistake only applies to the exact feature it was demonstrated with, rather than the broader category.
Fixing a symptom (adding a manual markForCheck() everywhere) instead of addressing the root cause (mutating data in place).
Skipping this kind of review once past the beginner stage, these mistakes still show up in advanced codebases.
Key Takeaways
Many Angular mistakes trace back to a small number of recurring root causes.
Async/Observable misunderstandings and reference-based change detection are two of the biggest categories.
Missing cleanup steps (subscriptions, timers, dynamic components) cause a large share of memory-leak-style bugs.
Recognizing the underlying pattern behind a mistake helps you avoid it in situations not explicitly covered here.
Pro Tip
When you hit a confusing Angular bug, ask which of the four root causes above it might be (laziness/async, reference equality, missing cleanup, or DI scope), it narrows the debugging search space dramatically before you even open DevTools.
You now have a consolidated view of common Angular mistakes and their root causes. Next, check the Angular Cheat Sheet for a fast, comprehensive reference.