lastName = signal('');
fullName = signal('');
isValid = signal(false);
🚨 Too much state = harder to manage
✅ Fix
Only store source of truth
firstName = signal('');
lastName = signal('');
fullName = computed(() =>
${this.firstName()} ${this.lastName()}
);
👉 Derive everything else
❌ Mistake 5: Mixing RxJS and Signals Without Strategy
this.userService.getUser().subscribe(user => {
this.user.set(user);
});
This works... but:
🚨 Problems:
unclear ownership
mixed patterns
harder debugging
✅ Better Approach
Be intentional:
use RxJS for async streams
convert to signals at boundaries
user = toSignal(this.userService.getUser());
👉 Clean separation
❌ Mistake 6: Putting Too Much Logic in Templates
{{ user()?.firstName + ' ' + user()?.lastName }}
🚨 Recomputed frequently
🚨 hard to maintain
✅ Fix
fullName = computed(() =>
${this.user()?.firstName} ${this.user()?.lastName}
);
{{ fullName() }}
🧠 The Correct Mental Model
Instead of thinking:
"When something changes, update everything manually"
Think:
"Define relationships — let Angular handle updates"
⚙️ When to Use What
Use Case Tool
Store state signal()
Derive values computed()
Side effects effect()
🚀 Why This Matters
Misusing signals leads to:
- unnecessary re-renders
- duplicated state
- complex logic
- harder debugging
Using them correctly gives you:
- predictable data flow
- better performance
- cleaner code
🔥 Final Thought
Signals are powerful — but only if used correctly.
Most bugs don’t come from the framework.
They come from:
using the right tools in the wrong way
💥 One Line to Remember
If you’re using effect() to manage state... you’re probably doing it wrong.
Master the mental model — and Angular becomes significantly simpler.