The composition API is a new and optional way of creating and organizing components in VueJS 3. It is based on the functional programming principle called composition. In this tutorial, we will use it to create a basic money conversion app.
Setting up Vue Project with the Composition API
Setting up a VueJS 3 project is not hard at all, but since the 3rd version of the framework is not out yet, then we will be actually using VueJS 2 with a composition-API plugin. The plugin will provide us with the features that we will need.
First, we can set up a standard VueJS application using VueJS CLI, then we will install the composition-api plugin:
$> vue create vue-3-money-converter
And we can just go with the default configuration. Furthermore, we will install the plugin:
$> npm i -S @vue/composition-api
Finally, we will add it to Vue:
import Vue from 'vue' import App from './App.vue' import VueCompositionApi from '@vue/composition-api' Vue.config.productionTip = false Vue.use(VueCompositionApi) new Vue({ render: h => h(App) }).$mount('#app')
Example of using Ref and Reactive
With the composition API, we now have a new method in our options object, called setup
.
In the setup method, we create reactive data, computed values, and register lifecycle hooks. In the end, we will return an object containing all the data, method, and computed values we will need in the template.
This is useful, for example for creating non-reactive variables and using them in the template, think of enums.
To create reactive data, we can use the reactive
function and theref
function. The difference is that the Ref
function will return an object that has a value property containing the value we passed initially.
If we want to change the value of the ref we have to mutate the value property. Or if it’s an object, we have to change one of its properties. On the other hand, reactive
accepts only objects and returns the same initial value passed.
Deciding which function to use depends on what you’re trying to achieve. However, here is a resource explaining why we should stick to ref all the time. Let’s see them in action first:
<template> <div> <input v-model="form.username" /> is submitted {{ isSubmitted }} </div> </template> <script> import { ref, reactive } from '@vue/composition-api' export default { setup () { const isSubmitted = ref(false) const form = reactive({ username: '' }) return { form, isSubmitted } } } </script>
Basically this is similar to creating an object and a boolean in the data methods. Now, let’s start building a small rates conversion app and explore the API further.
Fetching Conversion Rates with Axios
We will use Axios to fetch the exchange rates from the exchangerates.io API, First, let’s install Axios:
$> npm i -S axios
Next, we will create a new API folder and inside it an exchange-rates.js file. We will create an Axios instance pointed at the exchange rates API. Then, expose a method to fetch the data:
import { create as createAxiosInstance } from 'axios' const exchangeRatesApi = createAxiosInstance({ baseURL: 'https://api.exchangeratesapi.io' }) // this will wait for the promise to resolve the response object and then return the data property export const getLatest = async () => (await exchangeRatesApi.get('latest')).data
The create
method from Axios allows us to create a new instance, this will be a unique instance with its own configuration. If you’re dealing with multiple endpoints this is a great way to separate them. We specified a base URL which is the exchange rates API. Then, when we want to make a request we just specify the endpoint.
Since Axios request returns an object containing the data, The getLatest
method will return the data directly.
Converting Money using Reactivity
We will use now the composition API to call our API and display the rates.
First, in our main App.vue
component. We will create the setup method. Inside it, we will do the request to fetch the exchange rates using our API:
<template> <div id="app"></div> </template> <script> import { ref, onUnmounted, onBeforeMount } from '@vue/composition-api' import { getLatest } from '@/api/exchange-rates' export default { setup () { let interval const exchangeRates = ref({}) onBeforeMount(() => { interval = setInterval(async () => { exchangeRates.value = await getLatest() }, 1000) }) onUnmounted(() => { if (interval) { clearInterval(interval) } }) return { exchangeRates, } } } </script>
As you can see the beforeMount
and beforeDestroy
hooks have been replaced with methods onBeforeMount
and onUnmounted
. The trick here is to call these methods inside of the setup function so they can be registered in the component.
We created two variables, the interval variable is not reactive and we just use it to manage the interval that fetches the data periodically. We store the interval in a variable so that we clear it when the component is unmounted.
The other variable is reactive and it holds the result of our request. Since it’s a ref
, we have to assign the data to its value property.
Next, since we have the exchange rates, we will create an input that will hold the amount we want to convert. We will also create a computed value that will hold the result of the conversion since the result is a result of a computation (amount * rate), a computed value is a perfect choice for this.
<template> <div id="app"></div> </template> <script> import { ref, computed, onUnmounted, onBeforeMount } from '@vue/composition-api' import { getLatest } from '@/api/exchange-rates' // a function that takes the amount and rates and returns an mapped object containing the result for each rate const convertExchangeRates = (amount, exchangeRates) => { if (!exchangeRates.value.rates || !Object.keys(exchangeRates.value.rates).length) { return {} } return Object.keys(exchangeRates.value.rates) .reduce((rates, key) => { const rate = exchangeRates.value.rates[key] * amount.value rates[key] = rate.toFixed(2) return rates }, {}) } export default { setup () { let interval const exchangeRates = ref({}) // the amount is reactive since it will be used in a v-model const amount = ref(0) // the computed value calls the convertExchangeRates function const convertedRates = computed(() => convertExchangeRates(amount, exchangeRates)) onBeforeMount(() => { // ...code }) onUnmounted(() => { // ...code }) return { exchangeRates, amount, convertedRates } } } </script>
Finally, we will display the data:
<template> <div> <input v-model.number="amount" /> {{ exchangeRates.base }} <small>{{ exchangeRates.date }}</small> <ul> <li v-for="(rate, key) in convertedRates" :key="key" > {{ key }} : {{ rate }} </li> </ul> </div> </template> <script> // ...code </script>
Our result should look something like this:

Final Words
The new composition api brings more flexibity to how we create and use our Vue.js Component.
Further reading about the composition api in action:
I write code to solve real-world problems and build business applications as a Full-Stack developer. I enjoy being challenged and develop projects that require me to work outside my comfort and knowledge set. I’m interested in engineering, design, entrepreneurship, and startups. When driven by passion, making stuff is just fun.