Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it considered poor practice to use Axios or HTTP calls in components?

Tags:

vue.js

vuejs2

In this article, it says:

While it’s generally poor practice, you can use Axios directly in your components to fetch data from a method, lifecycle hook, or whenever.

I am wondering why? I usually use lifecycle hooks a lot to fetch data (especially from created()). Where should we write the request calls?

like image 434
Julien Le Coupanec Avatar asked Aug 23 '17 12:08

Julien Le Coupanec


2 Answers

Writing API methods directly in components increases code lines and make difficult to read. As far as I believe the author is suggesting to separate API methods into a Service.

Let's take a case where you have to fetch top posts and operate on data. If you do that in component it is not re-usable, you have to duplicate it in other components where ever you want to use it.

export default {
  data: () => ({
    top: [],
    errors: []
  }),

  // Fetches posts when the component is created.
  created() {
    axios.get(`http://jsonplaceholder.typicode.com/posts/top`)
    .then(response => {
      // flattening the response
      this.top = response.data.map(item => {
         title: item.title,
         timestamp: item.timestamp,
         author: item.author
      })
    })
    .catch(e => {
      this.errors.push(e)
    })

  }
}

So when you need to fetch top post in another component you have to duplicate the code.

Now let's put API methods in a Service.

api.js file

const fetchTopPosts = function() {
  return axios.get(`http://jsonplaceholder.typicode.com/posts/top`)
        .then(response => {
          // flattening the response
          this.top = response.data.map(item => {
             title: item.title,
             timestamp: item.timestamp,
             author: item.author
          })
        }) // you can also make a chain.
}

export default {
   fetchTopPosts: fetchTopPosts
}

So you use the above API methods in any components you wish.

After this:

import API from 'path_to_api.js_file'
export default {
      data: () => ({
        top: [],
        errors: []
      }),

      // Fetches posts when the component is created.
      created() {
         API.fetchTopPosts().then(top => {
            this.top = top
         })
         .catch(e => {
          this.errors.push(e)
         })

      }
    }
like image 55
Srinivas Damam Avatar answered Oct 07 '22 23:10

Srinivas Damam


It's fine for small apps or widgets, but in a real SPA, it's better to abstract away your API into its own module, and if you use vuex, to use actions to call that api module.

Your component should not be concerned with how and from where its data is coming. The component is responsible for UI, not AJAX.

import api from './api.js'

created() {
  api.getUsers().then( users => {
    this.users = users
  })
}

// vs.

created() {
  axios.get('/users').then({ data }=> {
    this.users = data
  })
}

In the above example, your "axios-free" code is not really much shorter, but imagine what you could potentially keep out of the component:

  • handling HTTP errors, e.g. retrying
  • pre-formatting data from the server so it fits your component
  • header configuration (content-type, access token ...)
  • creating FormData for POSTing e.g. image files

the list can get long. all of that doesn't belong into the component because it has nothing to do with the view. The view only needs the resulting data or error message.

It also means that you can test your components and api independently.

like image 33
Linus Borg Avatar answered Oct 08 '22 00:10

Linus Borg