Deprecate `recompute` on `Helper`?
- Dominant language
- No language data
- Stars
- 801
- Forks
- 409
- PR merge metrics
- No merged PRs in 30d
Description
The point of the `recompute` method is that you call it to trigger Ember to re-render the helper in some kind of callback, such as observers, promise callbacks, etc.
Since helpers are now auto-tracked, it should be possible to refactor any usage of `recompute` into setting tracked state and accomplish the same thing. In most cases, the transformation is pretty straightforward.
Before:
```js
class MyHelper extends Helper {
@service foo;
@observes('foo.bar.[]') onBarChanged() {
this.recompute();
}
compute() {
return this.foo.bar.map(...);
}
}
```
After:
```js
class MyHelper extends Helper {
@service foo;
@tracked bar = this.foo.bar;
@observes('foo.bar.[]') onBarChanged() {
this.bar = this.foo.bar;
}
compute() {
return this.bar.map(...);
}
}
```
The example uses an observer, because that is a common kind of callback used in this position, but it's ultimately unrelated to my point.I also think there are better ways to accomplish the same thing without using observers, in general, but that is also besides the point here.
For prosperity, here is a second example that doesn't use observers:
Before:
```js
const UNINITIALIZED = Object.freeze({});
class AwaitHelper extends Helper {
resolved = undefined;
promise = UNINITIALIZED;
compute([promise]) {
if (promise !== this.promise) {
this.resolved = undefined;
this.promise = promise;
Promise.resolve(promise).then(resolved => {
if (promise === this.promise) {
this.resolved = resolved;
this.recompute();
}
});
}
return this.resolved;
}
willDestroy() {
this.promise = UNINITIALIZED;
}
}
```
After:
```js
const UNINITIALIZED = Object.freeze({});
class AwaitHelper extends Helper {
@tracked resolved = undefined;
promise = UNINITIALIZED;
compute([promise]) {
if (promise !== this.promise) {
this.resolved = undefined;
this.promise = promise;
Promise.resolve(promise).then(resolved => {
if (promise === this.promise) {
this.resolved = resolved;
}
});
}
return this.resolved;
}
willDestroy() {
this.promise = UNINITIALIZED;
}
}
```
The general pattern is: instead of calling `recompute()`, just refactor into setting a piece of tracked state and use that tracked state in the `compute()` method.
Would be interested to see if there are any valid use cases this doesn't cover.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.