Vue Composables: Reusable Stateful Logic
A Vue composable is a function for bundling reusable stateful logic, like tracking mouse position. Use it to share complex logic like API fetches across components. The footgun: each component gets a fresh, independent state, not a shared one.
WHY IT EXISTS Frontend applications often have stateful logic that needs to be used in multiple places, such as fetching data or tracking browser events. Copy-pasting this logic across components is inefficient and error-prone. Composables were created to extract and reuse this stateful logic in a clean, scalable way.
THE MENTAL MODEL A composable is like a headless component: all logic, no template. It's a function that packages up Vue's reactive building blocks (ref, computed) and lifecycle hooks (onMounted) into a self-contained, reusable unit. Unlike a simple utility function that performs a single, stateless calculation (like formatting a date), a composable manages state that changes over time.
HOW IT WORKS By convention, composable functions are named with a use prefix, like useMouse or useFetch. Inside the function, you define reactive state using ref() or reactive(). You can then use lifecycle hooks to manage side effects, such as adding an event listener with onMounted and removing it with onUnmounted. The function returns the reactive state it manages, typically as an object, which a component can then use directly.
WHEN TO USE IT Use a composable whenever you find yourself writing the same stateful logic in more than one component. It's perfect for abstracting away browser APIs (e.g., localStorage, Fetch API), managing user interactions (e.g., mouse position, keyboard shortcuts), or handling any complex state that isn't tied to a single component's template.
WHEN NOT TO USE IT Do not use a composable when you need a single, shared state instance across your entire application. Each component that calls a composable gets its own separate instance of that state. For true global or cross-component state, use a dedicated state management library like Pinia. For simple, stateless logic, a plain JavaScript helper function is more appropriate.
ONE CANONICAL EXAMPLE A useMouse() composable can track the mouse position. The function creates two refs, x and y, initialized to 0. It uses onMounted to add a mousemove event listener to the window, which updates x.value and y.value on every move. It uses onUnmounted to remove that listener, preventing memory leaks. Finally, it returns { x, y }. Any component can then get live, reactive mouse coordinates by simply calling const { x, y } = useMouse().
Read the original → vuejs.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.