0

I have a simple component to display cryptocurrencies and I want to update the amount every second (and reflect the updated value). I can display the amount but my function to add 1 every second is not working. I tested with something else like alert() and that was working. Is it my selector?

<template>
  <div>
    <ul class="crypto-list">
      <li v-for="(currency, idx) in currencies" :key="idx" class="currency">
        <span class="currency__acronym">{{ currency.acronym}} </span>
        <h2 class="currency__name">{{ currency.name }}</h2>
        <span class="currency__amount"> {{ currency.amount }} </span>
      </li>
    </ul>
  </div>
</template>

<script>
  export default {
    name: 'Cryptocurrency',
    data() {
      return {
        currencies: [{
          name: 'Ethereum',
          acronym: 'ETH',
          amount: 1,
        },{
          name: 'ICON',
          acronym: 'ICX',
          amount: 40,
        },{
          name: 'Nano',
          acronym: 'XRB',
          amount: 14,
        }],        
      };
    },

    mounted () {
      this.addNumber();
    },

    methods: {
      addNumber: function() {
        setInterval(function() { 
          this.currencies[0].amount += 1;
          this.currencies[1].amount += 1;
          this.currencies[2].amount += 1;
        }, 1000);
      },
    },
  };
</script>
Mr X
  • 129
  • 2
  • 16
TkyStm
  • 71
  • 5

2 Answers2

1

The problem here is that the function passed into the setInterval function has a different context. We can use .bind to explicitly assign the context of the function passed into the setInterval.

addNumber: function() {
    setInterval(function(){ 
      ++this.currencies[0].amount;
      ++this.currencies[1].amount;
      ++this.currencies[2].amount;
    }.bind(this), 1000);
},

Edit:

For ES6 and above, you can use the arrow function syntax.

addNumber() {
    setInterval(() => { 
      ++this.currencies[0].amount;
      ++this.currencies[1].amount;
      ++this.currencies[2].amount;
    }, 1000);
},
Julian Paolo Dayag
  • 3,562
  • 3
  • 20
  • 32
  • Not a vue user, so might be wrong,. But to keep `this` context, don't you also want -> `addNumber: () => {` – Keith Jun 08 '18 at 09:56
  • @Keith, that is already handled by Vue as vue automatically binds the context into the component's methods. The cause of the out of context in here is the function passed into the `setInterval()`, so converting it into an arrow function will fix it. – Julian Paolo Dayag Jun 08 '18 at 09:58
  • Thank you! I will mark as solved when I can – TkyStm Jun 08 '18 at 09:59
  • Ok, did wonder if Vue handled this for you. – Keith Jun 08 '18 at 09:59
  • @TkyStm I've updated my answer, my previous answer was using ES6 arrow function syntax. I've updated it to include non-ES6 version as not all browsers currently support the arrow function syntax. – Julian Paolo Dayag Jun 08 '18 at 10:01
0

Its the use of setInterval, this is run every x second, in your case 1 sec because you passed 1000 as a parameter for the interval.

cf. setInterval

André Gomes
  • 142
  • 1
  • 6