Vue 3

Composables as State Management in Vue3

Sharing state between components in the Vue 3 world is easier than ever, thanks to composables. This new paradigm introduces a more…

Fotis Adamakis
Fotis Adamakis
Senior Software Engineer / Technical Writer
2 min read
February 12, 2024

Composables as State Management in Vue3

Composables as State Management in Vue3

Sharing state between components in the Vue 3 world is easier than ever, thanks to composables. This new paradigm introduces a more organized and scalable way to manage state and logic across the application.

Understanding Composables

In essence, a composable is a pattern rather than a specific functionality. It is implemented with a simple function that can hold the state and reusable code.

Here’s a quick look at what a useCounter composable look like:

import { ref } from 'vue';

export function useCounter(initialValue = 0) {

  const counter = ref(initialValue);

  function increment() {
    counter.value++;
  }

  function decrement() {
    counter.value\--;
  }

  function reset() {
    counter.value = initialValue;
  }

  return { counter, increment, decrement, reset };
}

We declare the counter as our reactive state and three functions that manipulate it. Notice that the composable has to return everything that other components can access.

From the component side, we can import and initialize the composable like this:

<template>
  <div>
    <h3>Counter Value: {{ counter }}</h3>
    <button @click="increment">Increment</button>
    <button @click="decrement">Decrement</button>
    <button @click="reset">Reset</button>
  </div>
</template>

<script setup>
import { useCounter } from "./useCounter";

const { counter, increment, decrement, reset } = useCounter();
</script>

[Try out this example](https://play.vuejs.org/#eNqNU01v2zAM/SuCLmlR1x6QW+sE27oeusM2bENPurgKk6q1JUMfaQDD/72kHCsO0LQ9RSHfIx8f6Y5/a9t8G4Bf8dJD09aVh6XQjJUrtY0PfD7OlzcmaA+W3Vd1gCvWdUzuI31fFgjYQx+C90azr7JW8nkhuNLSQgPaC768G99lMcBOkVZwIP0Y3x+RLDggwl/6PQKXxTBLWUwmxL9OWtV6hvDQYkQ1rbGedSw4GMft2dqahs3y4hCcXTOiS6Mdofc+ZCyNmrE0QMaiLKyzmJQ9O78mNUN/7Mwz7h3WW6tN/uSMxmV0JFxwaZpW1WB/t15hP8HR+mF+wau6Ni8/Y8zbANkYl48gn9+IP7kdxQT/Q5rsFgRPOV/ZDblH6dt/v2CH75RszCrUiH4niaabOpDGAfY96BXKnuCi2rtosdKb/+5250G7cSgSSsg+4gXHi7x5Z/SD3Hk+jzyhe3TxYDH6iC6mlVpYp11i7Rn6LzTsYnYdtKQW0wUprbyq6njtuLov59SbGg1bH29/QYWPwLRZwqWi6SrOYg3Sv2fnWyJcXCAjDnBESxd0gnZ5+SYtXtsJCqqdKp3yLX4CVn/6mJHa8/4VQUtyjw==)

This example showcases how composables help with code organization since our component is very lightweight and easy to understand.

Each time this composable gets initiated a new counter variable will be created keeping the state between instances separated.

However, in some scenarios, a shared state between instances is desired. This can be achieved by declaring the state outside the composable function:

import { ref } from "vue";

// state declared here will be shared
const sharedState = ref();

export function useComposable() {
  // state declared here will NOT be shared
  // and will be initialized every time
  const localState = ref();

  // Setters and getters for both
  // can be defined here

  return {
    sharedState,
    localState,
  };
}

This approach shows how flexible composables are, letting us manage state in a way that’s either separate for each instance or shared across them.

Conclusion

To wrap up, composables have truly redefined Vue 3 by offering simplicity, and modularity that feels natural and easy to understand. They can be used to abstract complexity away from components but also share state between them.

The Difference Between Composition, Composition API, and Composables in Vue 3

Fotis Adamakis

Fotis Adamakis

Senior Software Engineer / Technical Writer

Experienced software engineer writing about front end architecture, accessibility, system design, and developer productivity. Lessons from building and maintaining large-scale frontend applications, with a focus on practical patterns that make codebases easier to understand, scale, and evolve.

Barcelona, Spain