Reputation: 2237
I have a component with a viewport property. I want to listen for changes to this property, do some calculations and reflect a possibly changed value back to the property. My first attempt looked something like this:
class MyComponent {
@Prop()
viewport: ViewportData
@Watch('viewport)
viewportChanged(newValue: ViewportData, oldValue:ViewportData) {
... do some calculations
// Reflect value back as property
this.viewport = computedViewport;
}
}
This results in a stack overflow because reflecting the value back triggers another call to the watch function. I could prevent it by having a flag saying if this is an internal change or not. Something like this:
class MyComponent {
internalViewportChange = false;
@Prop()
viewport: ViewportData
@Watch('viewport)
viewportChanged(newValue: ViewportData, oldValue:ViewportData) {
if (this.internalViewportChange) {
this.internalViewportChange = false;
return;
}
... do some calculations
// Reflect value back as property
this.internalViewportChange = true;
this.viewport = computedViewport;
}
}
I don't like this approach. And is looking for something better. This problem could normally be solved by using getters and setters and a private variable keeping the actual state:
class MyComponent {
private _viewport: ViewportData
get viewport() {
return this._viewport;
}
set viewport() {
... do some calculations
// Reflect value back as property
this.viewport = computedViewport;
}
}
However, using Stenciljs the getters and setters are autogenerated. Any good ideas?
Upvotes: 2
Views: 1732
Reputation: 1862
I'd probably break the two-way prop setting, and create a unidirectional data flow, and emit events instead. Something like:
class MyComponent
@Event() viewportChanged: EventEmitter;
@Prop() viewport: ViewportData;
@State() _computedViewport: ViewportData;
@Watch('viewport') onViewportChanged(newValue) {
// do calculations
this._computedViewport = computedViewport;
this.viewportChanged.emit(this._computedViewport);
}
Internally, you'd only work on _computedViewport
, and the public viewportProp
is only there for users to update themselves. Ostensibly you could also expose a @Method()
that does the same thing.
Upvotes: 1