💡 Vue Typescript State Management : We can do better than “isLoading” in 2022

Sorry for the clickbait title, but I needed your attention đź‘€ 
Have you ever encountered code like this one :
new Vue({
  el: '#app',
  data () {
    return {
      info: null,
      loading: true,
      errored: false
    }
  },
  filters: {
    currencydecimal (value) {
      return value.toFixed(2)
    }
  },
  mounted () {
    axios
      .get('https://api.coindesk.com/v1/bpi/currentprice.json')
      .then(response => {
        this.info = response.data.bpi
      })
      .catch(error => {
        console.log(error)
        this.errored = true
      })
      .finally(() => this.loading = false)
  }
})

...

<div id="app">
  <h1>Bitcoin Price Index</h1>

  <section v-if="errored">
    <p>We're sorry, we're not able to retrieve this information at the moment, please try back later</p>
  </section>

  <section v-else>
    <div v-if="loading">Loading...</div>

    <div
      v-else
      v-for="currency in info"
      class="currency"
    >
      {{ currency.description }}:
      <span class="lighten">
        <span v-html="currency.symbol"></span>{{ currency.rate_float | currencydecimal }}
      </span>
    </div>

  </section>
</div>
It’s an example I found in the Vue documentation here https://vuejs.org/v2/cookbook/using-axios-to-consume-apis.html#Dealing-with-Errors
What if you have multiple things that could load, do you add a loading2 variable ? đź‘€
To solve this issue, you can use a variable for each async actions you have with this 4 “states” :
  • IDLE : the user didn’t trigger the action yet
  • WAITING : the action is ongoing
  • ERROR : there was an error
  • DONE : The action succeeded
  • Using an enum with the different states, and better naming, the code can be rewritten like this :
    enum AsyncState {
      IDLE = 'IDLE',
      WAITING = 'WAITING',
      ERROR = 'ERROR',
      DONE = 'DONE',
    }
    
    new Vue({
      el: '#app',
      data () {
        return {
          info: null,
    
          AsyncState,
          currentPriceLoadState: AsyncState.WAITING,
        }
      },
      filters: {
        currencydecimal (value) {
          return value.toFixed(2)
        }
      },
      mounted () {
        axios
          .get('https://api.coindesk.com/v1/bpi/currentprice.json')
          .then(response => {
            this.info = response.data.bpi
            this.currentPriceLoadState = AsyncState.DONE
          })
          .catch(error => {
            console.log(error)
            this.currentPriceLoadState = AsyncState.ERROR
          })
      }
    })
    
    ...
    
    <div id="app">
      <h1>Bitcoin Price Index</h1>
    
      <div v-if="currentPriceLoadState === AsyncState.WAITING">Loading...</div>
      <section v-else-if="currentPriceLoadState === AsyncState.ERROR">
        <p>We're sorry, we're not able to retrieve this information at the moment, please try back later</p>
      </section>
    
      <section v-else>
        <div v-for="currency in info" class="currency">
          {{ currency.description }}:
          <span class="lighten">
            <span v-html="currency.symbol"></span>{{ currency.rate_float | currencydecimal }}
          </span>
        </div>
    
      </section>
    </div>
    With better naming and this simple enum, you can almost cover all the use cases where you need to load one or multiple things and manage errors ✨
    If you want to manage different error messages, you can add another variable with an enum type like this :
    enum CurrentPriceLoadErrors {
      INVALID_CURRENCY = 'INVALID_CURRENCY',
      API_LIMIT_REACHED = 'API_LIMIT_REACHED',
      DEFAULT = 'DEFAULT',
    }
    Tell me in the comment section if you like this trick or not, and if you have an even better technique !
    And don’t forget to like and share this post if you liked it 💙

    27

    This website collects cookies to deliver better user experience

    💡 Vue Typescript State Management : We can do better than “isLoading” in 2022