I have a simple store that has the following structure:
class SearchStore {
@observable term = 'javascript';
@observable state = '';
results = observable.array([], {deep: false});
@computed
get isEmpty() {
return this.results.length === 0;
}
Here the computed property isEmpty() is never triggered if I set results to a new value. In fact, the second time I set results, it turns into a regular array and is no longer observable.
@action.bound
async search() {
/* ... */
this.results = searchResults;
}
However, if I declare results with a decorator:
@observable.shallow results = []
it works!. Is my usage of observable.array() not correct?
Just found out that I need to use the replace() API of the observable.array() to make it work properly.
@mweststrate, Looks like @observable.shallow is internally using that, I guess?
@pavanpodila the difference is that the first creates an observable _array_, and the second an _observable_ property, that will converts it value to an observable automatically if possible.
So this.results = does not change the array itself, and hence it will not be picked up if only the array was made observable. this.results modifies this instead, so you need the property to be observable to pick this up.
In general, I recommend to either use:
@observable.shallow results = []
// or
readonly results = observable.array([], {deep: false});
The readonly modifier (in typescript) will protect you against accidentally modifying the non-observable property, where a change to the obsrevable array was intended.
@observable.shallow is not internally using .replace; assigning a new value will assign a new array instance to the array property, not recycling the existing one. So purely theoretically speaking readonly results is slightly faster and safer then @observable.shallow; as the latter has two changing pieces (the object property and the array) and the first only one.
@mweststrate Thanks for the explanation. Is it right to say that the same behavior could be achieved if I had used the decorate() API?
decorate(SearchStore, { results: observable.shallow })
@pavanpodila yes
Awesome. Thanks Jiri
Regards,
--
Pavan Podila
On 9 Apr 2018, 12:56 PM +0530, Jiri Spac notifications@github.com, wrote:
@pavanpodila yes
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
Most helpful comment
@pavanpodila the difference is that the first creates an observable _array_, and the second an _observable_ property, that will converts it value to an observable automatically if possible.
So
this.results =does not change the array itself, and hence it will not be picked up if only the array was made observable.this.resultsmodifiesthisinstead, so you need the property to be observable to pick this up.In general, I recommend to either use:
The readonly modifier (in typescript) will protect you against accidentally modifying the non-observable property, where a change to the obsrevable array was intended.
@observable.shallowis not internally using.replace; assigning a new value will assign a new array instance to the array property, not recycling the existing one. So purely theoretically speakingreadonly resultsis slightly faster and safer then@observable.shallow; as the latter has two changing pieces (the object property and the array) and the first only one.