Description
It seems a reasonable assumption/invariant that when initialize
is called, the initial attributes have been set, and this is in fact true most of the time. However, it is not always true, because when the State is used as a child of a different State, then it is initialised with empty attributes (which will trigger initialize
, and only then is set
called on it with the initial attributes — but with silent: true
, so you cannot listen for this to happen in initialize
.
So, concrete example. I have a derived property that is expensive to calculate, so I don't want it to be a derived property, but something that I manually update (perhaps throttled or so). But I do want it to be immediately available for the initial data and not trigger a change event initially (to keep the behaviour consistent with how derived properties work), so I write this:
initialize() {
// Initially calculate but suppress events, to keep behaviour
// consistent with derived properties
this.set({ expensiveProperty: this._calculateExpensiveProperty() },
{ silent: true, initial: true });
// After that throttle updates to this property
this.listenTo(this, 'change:myDependency', _.throttle(() =>
this.expensiveProperty = this._calculateExpensiveProperty(), 1000));
},
Now this works fine in most cases, except when this State is used in children
of another State. The only workaround I currently see is to actually make a "dummy" derived property and do all this there (and make sure it only gets called once through some boolean or something).