Using Vue 3 Composition API for APIs

Tutorial 4 of 5

1. Introduction

In this tutorial, we'll be working with Vue 3's Composition API to interact with APIs. The aim is to refactor a Vue component that's currently using the Options API, to use the Composition API instead. By the end of this tutorial, you should be able to understand how to use the Composition API and apply it in your own projects.

What you'll learn:

  • An overview of Vue 3's Composition API
  • How to refactor a Vue component from Options API to Composition API
  • How to interact with APIs using Vue 3's Composition API

Prerequisites:

  • Basic understanding of Vue.js
  • Familiarity with JavaScript and ES6 syntax
  • Basic knowledge of HTML and CSS

2. Step-by-Step Guide

Vue 3's Composition API is a new way to manage state and logic in Vue components. It was designed to address the limitations of the Options API, providing better TypeScript support and making code more readable and maintainable.

Refactoring the Vue Component

Consider a Vue component that fetches data from an API using the Options API:

<template>
  <div>{{ data }}</div>
</template>

<script>
export default {
  data() {
    return {
      data: null
    };
  },
  mounted() {
    fetch('http://api.example.com')
      .then(response => response.json())
      .then(data => (this.data = data));
  }
};
</script>

Let's refactor this using the Composition API:

<template>
  <div>{{ data.value }}</div>
</template>

<script>
import { ref, onMounted } from 'vue';

export default {
  setup() {
    const data = ref(null);

    onMounted(async () => {
      const response = await fetch('http://api.example.com');
      data.value = await response.json();
    });

    return { data };
  }
};
</script>

In the Composition API, we move the logic to a setup method. We use ref to create a reactive reference, and onMounted to replace the mounted lifecycle hook. Notice how it makes our code more readable.

3. Code Examples

Example 1: Fetching data from an API

<template>
  <div>{{ users.value }}</div>
</template>

<script>
import { ref, onMounted } from 'vue';

export default {
  setup() {
    const users = ref(null);

    onMounted(async () => {
      const response = await fetch('https://jsonplaceholder.typicode.com/users');
      users.value = await response.json();
    });

    return { users };
  }
};
</script>

In this example, we're fetching user data from an API. users.value will contain the fetched data, which we can use in our template.

Example 2: Using watch to fetch data when a prop changes

<template>
  <div>{{ post.value }}</div>
</template>

<script>
import { ref, watch, onMounted } from 'vue';

export default {
  props: ['id'],
  setup(props) {
    const post = ref(null);

    const fetchPost = async () => {
      const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${props.id}`);
      post.value = await response.json();
    };

    onMounted(fetchPost);
    watch(() => props.id, fetchPost);

    return { post };
  }
};
</script>

Here, we fetch a post based on a prop id. If id changes, we refetch the post using watch.

4. Summary

In this tutorial, we've learned about Vue 3's Composition API and how to refactor a Vue component from the Options API to the Composition API. We've also seen how to fetch data from an API using the Composition API.

Next Steps

  • Try refactoring more complex components
  • Learn about more advanced features of the Composition API, like computed and watchEffect

Additional Resources

5. Practice Exercises

  1. Create a Vue component that fetches a list of albums from the API https://jsonplaceholder.typicode.com/albums and displays it. Use the Composition API.
  2. Modify the component from exercise 1 to update the albums when a prop userId changes.

Exercise 1 Solution

<template>
  <div v-for="album in albums.value" :key="album.id">
    {{ album.title }}
  </div>
</template>

<script>
import { ref, onMounted } from 'vue';

export default {
  setup() {
    const albums = ref(null);

    onMounted(async () => {
      const response = await fetch('https://jsonplaceholder.typicode.com/albums');
      albums.value = await response.json();
    });

    return { albums };
  }
};
</script>

Exercise 2 Solution

<template>
  <div v-for="album in albums.value" :key="album.id">
    {{ album.title }}
  </div>
</template>

<script>
import { ref, watch, onMounted } from 'vue';

export default {
  props: ['userId'],
  setup(props) {
    const albums = ref(null);

    const fetchAlbums = async () => {
      const response = await fetch(`https://jsonplaceholder.typicode.com/albums?userId=${props.userId}`);
      albums.value = await response.json();
    };

    onMounted(fetchAlbums);
    watch(() => props.userId, fetchAlbums);

    return { albums };
  }
};
</script>

In the first exercise, we fetch the albums and display them. In the second exercise, we update the albums when the userId prop changes.