Noob Question: How to correctly implement OnPush strategy?

Author
Kriti Yadav Author
|
5 days ago Asked
|
6 Views
|
0 Replies
0

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.OnPush in 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() with OnPush, 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 OnPush entirely? I just want my components to update efficiently!

0 Answers

No answers yet.

Be the first to provide a helpful answer!

Your Answer

You must Log In to post an answer and earn reputation.