Vue 3 Options to Composition API Migration
Tags: vue, webdev, refactorit, tutorial
Published: 2021-05-10 14:27:36

When the Vue3 'request for change' came out, one major change was accounted. A new API for writing the logic and handling the lifecycle of your Vue applications, called the composition API. It greatly differed from the familiar Options API that so many grew to love. This started a bit of a controversy which led to the Vue Team leaving support for the Options API in Vue3. They of course moved forward with composition but made it optional. 

This leads to both being fully supported and a great experience for people migrating from Vue 2 to Vue 3, allowing for gradual component to component refactoring. 

##Benefits of composition API vs options API

* Keep functionality blocks together
* Better performance
* Easier to extract and import logic 
* Cleaner code

For more indepth information on composition API read through [the Vue.js Docs](https://v3.vuejs.org/guide/composition-api-introduction.html)

##Here's an example migration from Options API to Composition API

First lets take a look at the component we'll be converting

Options API:
```vue 
<template>
  <div id="app">
    <h2>{{date}}</h2>
    <p>I drank {{cupsOfWater}} cups of water today 🥤</p>
    <button @click="drinkCup">Drink a cup</button>
    <p v-if='cupsOfWater > 0'>I drank the last cup at {{lastCup}}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      cupsOfWater: 0,
      date: '',
      lastCup: ''
    };
  },
  methods: {
    drinkCup() {
      this.cupsOfWater++
    }
  },
  watch: {
    cupsOfWater: function (val) {
      this.lastCup = new Date().toTimeString()
    }
  },
  mounted(){
    this.date = new Date().toDateString()
  }
};
</script>
```
[Options Codepen](https://codepen.io/mikhail-karan/pen/MWpWKjd)

This is just a simple app which allows you to track how many cups of water you drink a day


The lifecycle hooks are clearly seen here, and completely separated out. Leaving you to reason out what functionality and variables go together. Although in a small app this is fairly easy to see, in a larger codebase, it can get quite complicated.

To start the migration from Options to Composition we add the setup function, which is the only hook required in the composition API.

```javascript
setup(){
}
```

Then lets move the `cupsOfWater` declaration and `drinkCup()` incrementing function to `setup()`

```javascript
import {ref} from 'vue'
setup(){
    const cupsOfWater = ref(0)
    function drinkCup(){
      cupsOfWater.value++
    }

    return {
      cupsOfWater,
      drinkCup
    }

}
```

###Lets break down what we just did
* imported the `ref` functionality to show that a variable is meant to be reactive
* declared `cupsOfWater` as a reactive variable with a initial value of 0
* created a new function called `drinkCup()` which increments our reactive `cupsOfWater` variable, .value is required to access and change the value of reactive variables
* returned `cupsOfwater` and `drinkCup` so that it is accessible in the template (html)

We've still got a few more pieces of logic to move over to the `setup()` hook. Lets take a look at how it will look once it's fully migrated 

```vue
<template>
  <div id="app">
    <h2>{{date}}</h2>
    <p>I've drank {{cupsOfWater}} cups of water today 🥤</p>
    <button @click="drinkCup">I drank a cup</button>
    <p v-if='cupsOfWater > 0'>I drank the last cup at {{lastCup}}</p>
  </div>
</template>

<script>
import {ref, onMounted, watch} from 'vue'
export default {
  setup(){
    const cupsOfWater = ref(0)
    function drinkCup(){
      cupsOfWater.value++
    }
    
    const lastCup = ref('')
    watch(cupsOfWater, ()=>{
      lastCup.value = new Date().toTimeString()
    })
    
    let date = ref('')
    onMounted(()=>{
      date.value = new Date().toDateString()
    })
    
    return {
      date,
      cupsOfWater,
      drinkCup,
      lastCup
    }
    
  }
};
</script>
```
[Composition Codepen](https://codepen.io/mikhail-karan/pen/oNZNxrm)

The logic in the above codeblock is clearly separated into functional blocks. We immediately can tell which variables belong to which piece of functionality. 

Give it a try in your own projects! Vue2 now has a plugin [composition-api](https://github.com/vuejs/composition-api) that you can install. This will give you a good idea of how your future migration will go and might make it easier for you to adapt when the time comes to fully migrate. 

##The Goal

With this article I wanted to provide another side by side example of Options to Composition API migration. When I was looking through the documentation I didn't find enough of these. Let me know if you want me to create more!

###Check out HTML All The Things

HTML All The Things is a [web development podcast](https://podcast.htmlallthethings.com/) and [discord community](https://discord.com/invite/jweMCx9) which was started by Matt and Mike, developers based in Ontario, Canada. 

The podcast speaks to web development topics as well as running a small business, self employment and time management. You can join them for both their successes and their struggles as they try to manage expanding their Web Development business without stretching themselves too thin. 

Our latest episode takes the **bold** stance that [Vue is Better Than React](https://podcast.htmlallthethings.com/e/why-vue-is-better-than-react/)