Reputation: 8352
In the following scenario, Angular change detection is not triggering in the way I would expect it to. I am using ngrx-store to hold my application state.
In the above situation, there are two state updates (S1 -> S2 -> S1). However, at the end of this series of actions, my components OnChange is only triggering once (S1 -> S1). I am using a standard Observable with async pipe and child component with @Input.
@Component({
selector: 'app-parent-component',
template: `<app-time-entry [timeEntry]="timeEntry$ | async"></app-time-entry>`
})
export class ParentComponent {
timeEntry$: Observable<TimeEntryRow>;
constructor(private store: Store<AppState>) {
this.timeEntry$ = this.store.select(state => state.time.timeEntry);
}
}
@Component({
selector: 'app-time-entry',
template: `{{timeEntry.hours}}`
})
export class TimeEntryComponent {
@Input() timeEntry: TimeEntry;
}
Why is the change detection only happening once in this case? I have verified that my state is properly updating between each action, so why are the bindings only updated once? I would expect the async pipe to pass along the changed state twice, thus triggering the child components OnChange twice as well.
As suggested by Kevin below, adding a delay into the effect causes both OnChanges to trigger as expected. This would suggest that the Angular "tick" is happening after both state updates have finished.
Upvotes: 3
Views: 3808
Reputation: 3578
It might be normal. Your state changed twice during the same 'tick' (ie: you dispatching action A1 changed the state twice, one directly from the reducer handling your action, and the second time from the effect dispatching the second action).
But change detection is run once. So you only see the last change. I imagine if your effect was dispatching the action a latter time (maybe by using the delay operator) you would see OnChanges being called twice. I'm surprise you see the S2->S1 change though instead of S1->S1 (they have the same content, but are different objects since state is immutable), so it might not be what's happening.
Hard to see if this is what's happening without seeing all the code. What does your effect look like? Is it dispatching an action immediately, or is it doing some kind of AJAX request, and dispatching the action when it gets the result?
Upvotes: 3