Sharad Chand

Vue 3's Local <-> Global States

July 19, 2020

With the advent of Vue 3’s composition API, one may write local states and its tightly coupled actions like given below:

// maths.js
import { ref } from 'vue';

export function useMaths() {
  const val = ref(0);

  const increment = () => (val.value += 1);
  const decrement = () => (val.value -= 1);

  return {
    val,
    increment,
    decrement,
  };
}

This should look eerily similar to what React offers (if you have used React hooks).

The above code creates a reactive value called val and provides two actions to either increment or decrement this value.

This hook or a composable function can be imported into a component and used directly like so:

<template>
  {{ val }}
  <button @click="increment">Increment</button>
  <button @click="decrement">Decrement</button>
</template>

<script>
  import { useMaths } from './maths';

  export default {
    setup: () => {
      const { val, increment, decrement } = useMaths();
      return {
        val,
        increment,
        decrement,
      };
    },
  };
</script>

The component binds the value and actions to the Vue template. This useMaths hook can be imported into any number of components and the behaviour can be reused while keeping the states local to the component in which it was used.

Vue 3 not only allows us to compose the components and the UI but their behaviour as well.

But what do you do when you realise that the state should have been global instead?

There are times when you could be thinking that a particular state should be local to a component or a page. But as the app progresses on, this assumption may not hold true anymore.

Or there might be instances where you just wanted to experiment with the component and flesh out the internal workings while keeping the implementation simple by using local states. But once the experimentation phase is over you just want to reuse the code as much as possible and adapt it to use a global state.

In these above scenarios, Vue 3 gives us a new trick that we can do with ref that makes this sort of migration negligibly cheap to implement.

See what we do to make the state global in the code below?

// maths.js
import { ref } from 'vue';

const val = ref(0);

export function useMaths() {
  const increment = () => (val.value += 1);
  const decrement = () => (val.value -= 1);

  return {
    val,
    increment,
    decrement,
  };
}

Just move the ref out of the context of the hook and make it global. Vue will take care of the rest. Each component that uses this hook will all share the same val. Now, isn’t that something?

PS: This can be done with reactive as well.

© 2020 Sharad Chand