State and reactivity in Vue

June 2020 | Permalink

Illustration by Barbara

In one of my previous articles, I mentioned how it is possible to design a simple state manager in Vue by using observable. The Observable API has been available in Vue since version 2 however, with version 3 the reactive object is no longer directly modified but proxied into. Let's have a look how both work in detail:

In Vue 2, a reactive store might look like this:

// store.js
export const store = Vue.observable({ orders: 0 });

We can provide the components with a basic dispatch function that will collect an action with a payload and that will take care of updating the state. Also, we might want to provide a getters helper so that the store values can be reached as computed properties:

// store.js
export function dispatch(type, payload) {
    switch(type) {
        case 'increment-orders':
            Object.assign(store, { orders: store.orders + payload });
            break;
        default:
            //
    }
}

export function getters(orders) {
    return {
        orders: () => store.orders
    }
}

In our Vue component, we register the getters and use dispatch to notify the store about a user event:

<template>
    I have {{ orders }} orders on my account. 
    <a @click="increment()">add order</a>
</template>

<script>
import { dispatch } from 'store';

return {
    computed: { ...getters() },
    methods: { 
        increment() {
            dispatch('increment-orders', 1); 
        } 
    }
};
</script>

Vue 3 and the Composition API

With the introduction of the Composition API, operating with reactive properties is much simpler. The above example could be easily refactored to follow the new constructs. Here, reactive replaced the functionality that observable was providing:

// store.js
import { reactive } from 'vue';

export const store = reactive({ orders: 0 });

// Component.vue
import { store, dispatch } from './store';

export default {
    setup() {
        return { store };
    },
    methods:{
        increment() {
            dispatch('increment-orders', 1);
        }
    }
}

You can read more about the Vue Composition API on its RFC Page.