Skip to content
tezvyn:

Why does an OnPush Angular child not update when its input changes?

Source: angular.devMediumHow cards are made

Why does an OnPush Angular child not update when its input changes?

Tests OnPush reference equality and manual change detection. Strong answers name: in-place object mutation as the root cause; ChangeDetectorRef.markForCheck or detectChanges to force updates; and Angular Signals as a modern path.

What's really being asked

This question probes whether you understand Angular's component-level change detection strategy and the difference between reference and value equality in JavaScript. OnPush is designed for performance, and misusing it by mutating state is one of the most common production bugs in Angular applications. The interviewer wants to hear that you know when Angular skips checks and how to force them correctly without destroying performance.

The full answer

First, state that OnPush components run change detection only when a new reference is passed to an Input, an event binding fires from the component or its children, or an async pipe receives a new emission. Second, identify the root cause: the parent mutated an object or array in place, such as calling push or assigning a property directly, so the input reference never changed and Angular's SimpleChanges check found nothing. Third, mention edge cases where code runs outside NgZone, such as some third-party callbacks or WebSocket handlers, which also prevents automatic detection. Fourth, explain the two programmatic fixes: ChangeDetectorRef.markForCheck marks the component and its ancestors for checking in the next change detection cycle, which is the preferred light-touch fix for OnPush, while ChangeDetectorRef.detectChanges runs change detection immediately on the component and its descendants, which is heavier but useful when you need synchronous UI updates. Fifth, note that Angular v22 Signals offer a modern alternative where signal-based inputs trigger updates automatically through fine-grained reactivity rather than reference checks.

The mistakes people make

Saying that OnPush performs deep comparison on object properties. Recommending ApplicationRef.tick as the first solution, which forces global change detection and defeats the purpose of OnPush. Confusing markForCheck with detectChanges by claiming both execute immediately. Suggesting to switch the child back to Default change detection as the primary fix, which signals you do not understand performance optimization. Mentioning setInterval or setTimeout without explaining zone implications.

What usually comes next

How would you refactor this component to use signals instead of manual change detection triggers? When is detectChanges actually necessary versus markForCheck? How do you enforce immutability across a large team?

A concrete example

Imagine a parent component holds an array of orders and passes it to an OnPush child grid. If the parent calls orders.push(newOrder), the grid never updates because the array reference is identical. The correct fix is to create a new reference with orders = [...orders, newOrder], which triggers OnPush. If the child still needs an update after an internal async fetch, you inject ChangeDetectorRef and call markForCheck. In Angular v22, you might instead define the input as a signal and update it with orders.update(current => [...current, newOrder]), letting the signal notify subscribers directly.

Interview question

An OnPush child fails to update after its parent pushes an item into an input array. What is the root cause?

  • a.Angular OnPush performs deep equality checks and skips updates when nested properties match.
  • b.The parent code is executing outside NgZone, preventing automatic change detection.
  • c.The array reference never changed, so Angular's input check found no difference.Correct
  • d.You should call ApplicationRef.tick in the parent to force the child to update immediately.
Why?

OnPush components rely on reference equality for inputs, so in-place array mutation leaves the reference unchanged and Angular skips the check. Option A is tempting because developers often assume frameworks perform deep property comparisons, but OnPush intentionally avoids that overhead.

Just read this? Test yourself on what you have been reading.

Read the original → angular.dev

You just looked this up. Could you explain it out loud?

That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Open roles that interview on angular — each one lists the topics its interview covers.

See open roles