0

I need to get store data when some properties change. Property value exist in the service, so I re-execute function using {{did-update}}. But this action fall into infinite loop when the service property value changes.

This is my code.

  • js file
export default class CurrentApplications extends Component {

  @service store;
  @service current;
  @service permissions;

  @tracked currentApplications = emberA([]);

  constructor() {
    super(...arguments);
    next(()=> {
      this.currentApplications.pushObject(this.loadCurrentApplications.perform());
    });
  }

  @task
  *loadCurrentApplications() {
    const query = {
      page:     this.currentApplications.length + 1,
      per_page: 10,
      from:     moment().subtract(1, 'minutes').format(),
      until:    moment().add(1, 'minutes').format(),
      state:    ["accept", "assigned", "cancelled", "superseded"]
    };

    const locationId = this.current.locationId;
    if (locationId) query.location_id = locationId;

    if (get(this, 'current.user.isStaff')) {
      set(query, 'user_ids', get(this, 'current.user.id'))
    }

    return yield this.store.query('shift-application', query);
  }

  @lastValue('loadCurrentApplications') currentApplicationsCurrentPage;

  @task
  *loadForNewLocation() {
    this.currentApplications.clear();
    this.currentApplications.pushObject(this.loadCurrentApplications.perform());
  }

  get applicationsLoaded() {
    return this.currentApplications.length &&
           !this.currentApplications.lastObject.isRunning;
  }

  get hasMorePages() {
    return this.currentApplications.length &&
           !this.currentApplications.lastObject.isRunning &&
           this.currentApplicationsCurrentPage.meta.page < this.currentApplicationsCurrentPage.meta.pages;
  }

  @action
  nextPage() {
    this.currentApplications.pushObject(this.loadCurrentApplications.perform());
  
}
  • hbs file
{{did-update (perform this.loadForNewLocation) this.current.locationId}}
<div class="columns is-multiline dashboard__sidebar__row mb-0">
  <div class="column is-12">
  ...
  </div>
</div>

When the this.current.locationId changes, loadForNewLocation fall into loop execute. How should I solve this problem?

1 Answers1

0

The issue is this, in your template:

(perform this.loadForNewLocation)

loadForNewLocation accesses tracked data, this.currentApplications, which means that when this.currentApplications changes, the (perform) helper re-runs (because helpers auto-track).

To get around this, you'll want to change your did-update callback to (instead of being the result of the perform helper), to something like this:

{{did-update this.getNewLocations this.current.locationId}}

where

getNewLocations = () => {
  this.loadForNewLocation.perform();
}

For more information about this problem, I have a more in-depth write up here: https://github.com/NullVoxPopuli/ember-resources/issues/340#issuecomment-1028533534

NullVoxPopuli
  • 61,906
  • 73
  • 206
  • 352
  • The link above was definitely helpful. Great article. Anyway I had another problem. When I wrap {{did-update}} with
    , the problem was solved. Can you tell me about the difference between using {{did-update}} alone and using it wrapped with
    ?
    – KingStar1001 Sep 15 '22 at 05:27
  • can you open another question with code snippets? (and link it back here) I'm not sure I understand (I do have a hunch though) – NullVoxPopuli Sep 15 '22 at 11:44