tracked-tools / ember-could-get-used-to-this

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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:

{{# let (load-data (hash name='xx' age=30)) as |resource|}}
  {{log resource}}
{{/let}}

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?

{{#let (load-data (hash name='xx' age=30)) as |resource|}}
  {{log resource}}
{{/let}}

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:

{{#let (member-fetcher id=this.member) as |memberFetcher|}}
    {{#if memberFetcher.data}}
        <GhMemberDetails @member={{memberFetcher.data}} />
    {{/if}}
{{/let}}

Error:
Screenshot 2022-01-25 at 16 19 26

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 🤦