Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why executes a computed function twice? #35

Closed
p4m opened this issue Oct 11, 2016 · 3 comments
Closed

Why executes a computed function twice? #35

p4m opened this issue Oct 11, 2016 · 3 comments

Comments

@p4m
Copy link

p4m commented Oct 11, 2016

I have a component that collects data from Firebase. The data contains subscriptions (236) of people that subscribe to courses (21) with a specific date.

In a computed property (of the component) I get the unique dates and store them in an array. This array is the base for the v-for in the component. So a list of unique dates is listed (in a panel-group), and every panel shows the subscribers for that particular date.

I console log this computed property (named courseDates) and see that this function is executed twice. Btw, the first time it executes no date is there (yet). In the second cycle it has the data.

Am I doing something wrong here, that it executes twice to collect the data from firebase? Does this sound familiar? Is this a bug? Hope to here from you...

Below the code of the component...
If needed, I can share code via Github repo.

Vue.component('my-subscriptions', {

  props: ['display', 'signInStatus'],

  data: function () {
    return {
      title: 'subscriptions',
      selectedDate: 0,
      filterBy: '',
      date: '',
      loading: true
    }
  },

  firebase: {
    subscriptions: db.ref('subscriptions').orderByChild('date');
  },

  mounted: function() {
    // because loading is cached, set this.loading to true
    this.loading = true;
  },

  events: {},

  computed: {

    courseDates: function() {
      console.log('courseDates'); // get executed twice
      var dates = _.sortedUniqBy(this.subscriptions, 'datum'),
          datesSorted = [];

      // only if there are any dates
      if(dates.length>0){
        // loop through the dates
        dates.forEach(function(data) {
            var date = moment(data.date, "DD-MM-YYYY").format('x');
            // collect the newly formated dates
            if(data.date !== undefined) {
              datesSorted.push(date);
            }
        });
        // then sort them on chronologic order
        datesSorted.sort(function(a,b) {
          return b-a;
        });
        // finaly, format the dates in a format (DD-MM-YYYY) originally stored
        // for queryingitg purpose
        var datesFormated = datesSorted.map(function(date) {
          var d = moment(date, 'x').format('L');
          return d;
        });
      }
      return datesFormated;
    },

  },

  methods: {},

  template: `
<div class="panel panel-default" v-for="(date, index) in courseDates">....</div>
`
});
@posva
Copy link
Member

posva commented Oct 13, 2016

That behaviour is intended. The computed property reacts first to the empty array then firebases fetches data and updates the array again. Nothing to worry about 😉

@posva posva closed this as completed Oct 13, 2016
@jhoganrg
Copy link

jhoganrg commented Apr 1, 2020

This is a solution I implemented for what I think to be a similar challenge. ... may or may not be helpful Cheers --

  <v-data-table
      class="ma-3"
      :disable-sort="true"
      :footer-props="{
        itemsPerPageOptions: [5, 10, 25, 100]
      }"
      :headers="headers"
      :loading="loadingChanges"
      :items="tableOptions.records"
      :items-per-page="tableOptions.per_page"
      :options="tableOptions"
      :server-items-length="tableOptions.total_records"
      :search="tableOptions.search"
      @update:options="onTableOptionsUpdate($event)"
    >

methods: {
...
onTableOptionsUpdate: _.debounce(function (newTableOptions) {

   /*
     * Why? Cuz otherwise everything runs twice.
     * 
     * Again you ask Why?
     * 
     * Our TableOptions are instantiated in the store with defaults.
     * On Load we make a call that hydrates the tableOptions... Good
     * 
     * But
     * 
     * That is an update to tableOptions (even if it is the same values) which fires the 
     * @update:options event, which in turn goes out to the API again with the same values as onLoad... BAD
     */
    if (this.apiCallCount === 0) {
      this.getLienholderAddresses(transformedTableOptions);
      this.apiCallCount++;
    } else {
      this.apiCallCount = 0;
    }

@did
Copy link

did commented Apr 22, 2020

I know this is a closed issue but I faced the same issue in my app. Here is my solution.

If I take the initial example, I was watching the subscriptions data to stop my loader.
It turned out that it was called twice when I was calling this.$bind('subscriptions', ...).
The first call returned an empty array, the second call, the collection. Oddly, the second call might not occur if my collection was really empty.
Anyway, the trick is to use .then(subscriptions => { /* stop my loader */ } when I do the binding. The promise will be called once anytime.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants