Resource hooks are constantly re-run
mydea opened this issue · comments
I have just tried write a resource "helper" like this:
export default class LoadDataResource extends Resource {
@service store;
@tracked data = null;
@tracked isLoading = true;
@tracked isError = false;
get value() {
return {
isLoading: this.isLoading,
isError: this.isError,
data: this.data,
};
}
setup() {
let options = this.args.positional[0];
taskFor(this.loadDataTask).perform(options);
}
teardown() {
taskFor(this.loadDataTask).cancelAll();
}
@task
*loadDataTask(options) {
this.isLoading = true;
this.isError = false;
try {
let data = yield this.store.loadData(options);
this.isError = false;
this.isLoading = false;
this.data = data;
} catch (error) {
this.isError = true;
this.isLoading = false;
this.data = error;
}
}
}
Used like this:
However, that goes into an infinite loop of setup/teardown of the resource.
Hmm, now that I try it more, I seem to get the same behavior when converting the task to an async function.
I have managed to make a pretty minimal case where it doesn't work for me:
export default class LoadDataResource extends Resource {
@tracked isLoading = true;
get value() {
return {
isLoading: this.isLoading,
};
}
setup() {
this.loadData();
}
async loadData() {
await new Promise((resolve) => {
setTimeout(() => resolve([]), 1000);
});
this.isLoading = false;
console.log('load data completed');
}
}
Every time isLoading
is set, the setup()
hooks seems to be called again, so every 1000ms.
How are you invoking the Resource
? Still like this?
Does this "fix" it?
setup() {
setTimeout(() => this.loadData()); // Could also use `next` from `@ember/runloop`.
}
This is the problem with long timelines to implement things, I forgot that there were fundamentally two layers of caching going on here, have a PR coming up!
@pzuraq @buschtoens this is still happening on "ember-could-get-used-to-this": "^1.0.1"
with a fairly exact scenario posted here.
I'm hitting a similar error.
Resource:
import {Resource} from 'ember-could-get-used-to-this';
import {inject as service} from '@ember/service';
import {task} from 'ember-concurrency-decorators';
import {tracked} from '@glimmer/tracking';
export default class MemberFetcher extends Resource {
@service store;
@tracked data = null;
@tracked isLoading = false;
get value() {
return {
data: this.data,
isLoading: this.isLoading
};
}
setup() {
const {id} = this.args.named;
if (!id) {
return;
}
console.log('setup', id);
this.fetchMemberTask.perform(id);
}
@task
*fetchMemberTask(id) {
this.isLoading = true;
const member = yield this.store.findRecord('member', id);
this.isLoading = false;
this.data = member;
}
}
Invocation:
Does the library need a new release? Looks like the fix was committed after the last release was cut. Ignore that, I misread the commit timeline 🤦