Using Axios with Vue

Oct 10, 2019

Vue doesn't have a built-in HTTP request library. The official Vue cookbook recommends using Axios to interact with REST APIs.

This tutorial will use the excellent JSONPlaceholder API to provide sample data. For example, if you type https://jsonplaceholder.typicode.com/users/1 in your browser's URL bar, you'll get the below response:

{
  "id": 1,
  "name": "Leanne Graham",
  "username": "Bret",
  "email": "Sincere@april.biz",
  "address": {
    "street": "Kulas Light",
    "suite": "Apt. 556",
    "city": "Gwenborough",
    "zipcode": "92998-3874",
    "geo": {
      "lat": "-37.3159",
      "lng": "81.1496"
    }
  },
  "phone": "1-770-736-8031 x56442",
  "website": "hildegard.org",
  "company": {
    "name": "Romaguera-Crona",
    "catchPhrase": "Multi-layered client-server neural-net",
    "bs": "harness real-time e-markets"
  }
}

Displaying Response Data

The axios.get() function executes an HTTP GET and returns a promise. So calling await axios.get('https://jsonplaceholder.typicode.com') gets you an object whose data property contains the above JSON data.

Remember that Vue hooks can be async functions. So that means you can use async/await to execute the Axios request.

const url = 'https://jsonplaceholder.typicode.com/users/1';

const app = new Vue({
  data: () => ({ user: null, error: null }),
  // Display username if available, and error message if not
  template: `
    <div>
      <div v-if="user != null">
        {{user.name}}
      </div>
      <div v-if="error != null">
        {{error.message}}
      </div>
    </div>
  `,
  mounted
});

async function mounted() {
  try {
    this.user = await axios.get(url).then(res => res.data);
    this.error = null;
  } catch (error) {
    this.user = null;
    this.error = error;
  }
}

With Server-Side Rendering

Unfortunately, the above example as written won't work with Vue server-side rendering because:

  1. Vue's renderToString() doesn't call mounted hooks, because the component is never actually mounted.
  2. Vue's renderToString() doesn't wait for async hooks to execute, so even if you used created, the above example wouldn't work.

However, there is an easy workaround. Just call the mounted() function manually and await on it.

await mounted.call(app);
const data = await renderToString(app);
data; // <div data-server-rendered="true"><div>Leanne Graham</div> <!----></div>

More Vue Tutorials