Noob Question: How to correctly implement OnPush strategy?
Hey everyone,
I'm a total newbie to Angular, and after reading up on some previous discussions here about change detection (especially after being stuck on it myself), I'm trying to wrap my head around the OnPush strategy to optimize my app's performance. My goal is to achieve proper angular change detection optimization in my components.
I thought implementing OnPush would prevent unnecessary re-renders in child components if their inputs haven't changed by reference. However, I'm still seeing child components re-render even when I'm only modifying properties inside an object passed as an input, or when a parent component's local state changes unrelated to the child. It's quite confusing for a beginner.
Here's what I've tried so far:
- Set
changeDetection: ChangeDetectionStrategy.OnPushin my child component. - Tried to pass immutable data where possible, but I'm probably doing it wrong for nested objects.
- Experimented with
this.cdr.markForCheck()in the child component, but it seems to trigger too often or not at all when I expect it to.
Let me illustrate with an example scenario:
// parent.component.ts
export class ParentComponent {
user = { name: 'Alice', age: 30, address: { city: 'NY' } };
updateName() {
this.user.name = 'Bob'; // This doesn't trigger child re-render (expected)
}
updateCity() {
this.user.address.city = 'LA'; // This also doesn't trigger child re-render (expected, but if I want it to, how?)
// this.user = { ...this.user, address: { ...this.user.address, city: 'LA' } }; // This works, but cumbersome
}
triggerParentChange() {
console.log('Parent change triggered'); // Parent's own local state change
}
}
// child.component.ts
@Component({
selector: 'app-child',
template: `
<div>Child Component: {{ user.name }} from {{ user.address.city }}</div>
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildComponent {
@Input() user: any;
constructor() { console.log('Child component constructed/re-rendered'); } // This logs more often than expected
}
Here's what I observe in the console output:
// Initial load
Child component constructed/re-rendered
// Clicking 'updateName' (no child log, expected)
// Clicking 'updateCity' (no child log, expected, but I want it to update the view)
// Clicking 'triggerParentChange' (sometimes child logs re-render, sometimes not, very confusing)
My core questions are:
- When exactly do I need to use
ChangeDetectorRef.markForCheck()withOnPush, especially for nested object changes? - What's the best practice for ensuring child components update their view when only a property of an input object (like
user.address.city) changes, without rebuilding the entire object every time from the parent? - Am I misunderstanding the core concept of
OnPushentirely? I just want my components to update efficiently!
0 Answers
No answers yet.
Be the first to provide a helpful answer!