Reputation: 4172
I'm sure there is a reasonable explanation for this, but it is really baffling to me why object properties are updated in the view but variables that are primitive types are not. I'm using observables from ngrx/store so that could be the reason, but I feel like I've seen this in other async situations so I'm trying to understand it.
For example, I have this template:
<h1>{{data.counter}}</h1>
<h1>{{dataCounter}}</h1>
Then in my TypeScript class for the component I have something like this:
ngOnInit() {
this.store.select('mainStoreReducer')
.subscribe((data: MyState) => {
this.zone.run(() => {
this.dataCounter = data.counter;
this.data = data;
});
}
When I looks at the screen the text that represents the dataCounter variable is not updated, but the text that represents data.counter is updated! Even that extra block to force zone.js to run doesn't help. dataCounter still shows the original text (note: what actually happens is dataCounter gets the value for the initial state, but it never updates when the subscribe is fired at a later time. The text for data.counter always updates). Can someone please explain this?
Here is a plunkr of the situation I'm describing: https://plnkr.co/edit/gEeAKK31Yo6kATjFQY08?p=templates
Upvotes: 0
Views: 879
Reputation: 214007
As you can notice subscribe handler is not executed after dispatching event CHANGE_STUFF
data.counter
is getting updated because inside your mainStoreReducer
you mutate this object instead of creating new object.
Here is place where you went wrong:
let newState = Object.assign(state);
it should be:
let newState = Object.assign({}, state);
or a better way:
let newState = Object.assign({}, state, { counter: 13 });
For better understanding see Reducers documentation
Upvotes: 3