Call nuxt/axios module from external js/ts file

Viewed 2288

I am new to vue and trying to build my first vue app using nuxtjs. My problem right now has to do with architecture and folder structure.

In my other non-vue apps I always have a "services" directory where I keep all my code that makes http requests.

example under my services folder I will have a auth.ts file that contains code that posts login credentials to my API. This file/class returns a promise which I access from within my store.

I am trying to do this with vue using nuxtjs but I realised I am unable to access the axios module from anywhere aside my .vue file.

This is an example of how my code is now:

<template>
  ...
</template>

<script lang="ts">
import Vue from 'vue'
import ActionBar from '../../components/ActionBar.vue'

export default Vue.extend({
  components: { ActionBar },
  data() {
    return {
      example: ''
  },
  methods: {},
  mounted() {
    this.$axios.$get('/examples').then((res) => {
      this.examples = res.data;
    })
  }
})
</script>

<style>
...
</style>

I would like to move the axios calls to their own files in my services folder. How do I do this?

1 Answers

what you can do is create a file inside the ./store folder, let's imagine, ./store/products.js, that will create a products store, inside, simple getters, mutations and actions:

export const state = () => ({
    products: [],
    fetchingProducts: false,
})

export const getters = {
    getAllProducts(state) {
        return state.products
    },
    hasProducts(state) {
        return state.products.length > 0
    },
    isFetchingProducts(state) {
        return state.fetchingProducts
    },
}

export const mutations = {
    setInitialData(state, products) {
        state.products = products
    },
    setLoadingProducts(state, isLoading) {
        state.fetchingProducts = isLoading
    },
}


export const actions = {
    async fetchProducts(context, payload) {
        context.commit('setLoadingProducts', true)

        const url = `/api/example/${payload.something}`
        const res = await this.$axios.get(url)
        context.commit('setInitialData', res.data)
        context.commit('setLoadingProducts', false)
    },
}

then in your .vue file, you can now use the store as:

<template>
  <div>
    <div v-if="isFetchingProducts"> loading... </div>
    <div v-else-if="!hasProducts">no products found</div>
    <div v-else>
      <ul>
        <li v-for="product in allProducts" :key="product.id">
          {{ product.name }}
        </li>
      </ul>
    </div>
  </div>
</template>

<script>
  import { mapGetters } from 'vuex'

  export default {
    data () {
      return {
        products: []
      }
    },
    methods: {
      ...mapGetters({
        isFetchingProducts: 'products/isFetchingProducts',
        allProducts: 'products/getAllProducts',
        hasProducts: 'products/hasProducts',
      })
    },
    mounted() {
      this.$store.dispatch('products/fetchProducts', {})
    },
  }
</script>

<style>
...
</style>

remember that:

  • to call a store action, you should use $store.dispatch()
  • to call a mutation, you should use $store.commit()
  • to call a getter, you should use $store.getter()

you can also use the Vuex helper mapGetters, mapActions and even mapMutations


You might also know that you can leverage the Plugins in Nuxt, that article has demo code as well so you can follow up really quick

Related