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…

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

