What Are Composables in Vue.js? A Beginner’s Guide with Examples

Vue.js is a powerful JavaScript framework that offers flexibility and reusability. One of its most powerful features is Composables, which allow developers to organize and reuse logic efficiently.
In this blog post, we’ll explore:
✅ What are Composables?
✅ Why use Composables?
✅ How to create and use Composables in Vue 3
✅ Best practices for writing clean and reusable Composables

What Are Composables in Vue.js? A Beginner’s Guide with Examples Image

What is a Composable in Vue.js?

Composables are reusable functions that encapsulate logic using Vue’s Composition API. They allow you to extract and share stateful logic across components, making your code more modular and maintainable.

Think of them as custom hooks (similar to React’s hooks) that help manage side effects, state, and business logic outside of components.

Why Use Composables Instead of Mixins or Plugins?

🔹 Reusability – Avoid duplicating logic across components.
🔹 Better Organization – Keep business logic separate from UI.
🔹 Testability – Easier to test logic in isolation.
🔹 Cleaner Components – Reduce component complexity.

How to Create a Vue 3 Project

Before using Composables, let’s set up a Vue 3 project.

Step 1: Install Node.js

Ensure you have Node.js (v16 or later) installed.

Step 2: Install Vue CLI or Vite

You can use either:

  • Vue CLI (traditional)

    npm install -g @vue/cli
    vue create my-vue-app
    cd my-vue-app
    npm run serve
  • Vite (faster & recommended)

    npm create vue@latest
    cd my-vue-project
    npm install
    npm run dev

Step 3: Project Structure

my-vue-app/  
├── src/  
│   ├── components/  
│   ├── composables/  
│   ├── App.vue  
│   └── main.js  
└── package.json

How to Create a Composable in Vue 3

  •   Basic vuejs Composable Example: useCounter

      Let’s create a simple counter composable:

    src/composables/useCounter.js

    // useCounter.js
    import { ref } from 'vue';
    
    export function useCounter(initialValue = 0) {
      const count = ref(initialValue);
    
      function increment() {
        count.value++;
      }
    
      function decrement() {
        count.value--;
      }
    
      function reset() {
        count.value = initialValue;
      }
    
      return { count, increment, decrement, reset };
    }
    
  •  Using the Composable in a Component

    src/components/CounterComponent.vue

    <script setup>
    import { useCounter } from './useCounter';
    const { count, increment, decrement, reset } = useCounter(0);
    </script>
    <template>
     <div>
       <p>Count: {{ count }}</p>
       <button @click="increment">+</button>
       <button @click="decrement">-</button>
       <button @click="reset">Reset</button>
     </div>
    </template>

Best Practices for Writing Reusable Composables

Name them with use prefix (e.g., useCounter, useFetch) for clarity.
Keep them focused – A composable should handle a single responsibility.
Use reactive state (ref, reactive, computed) for reactivity.
Handle cleanup (e.g., onUnmount for event listeners).

Real-World Examples of Vue Composables

Let’s explore some practical examples of how composables can be used in Vue.js applications.

  1. useFetch – Fetching Data: A common use case is creating a composable for handling data fetching. This composable will allow you to fetch data and manage loading/error states.

    import { ref } from 'vue';
    
    export function useFetch(url) {
      const data = ref(null);
      const error = ref(null);
      const isLoading = ref(true);
    
      fetch(url)
        .then((response) => response.json())
        .then((result) => {
          data.value = result;
          isLoading.value = false;
        })
        .catch((err) => {
          error.value = err;
          isLoading.value = false;
        });
    
      return { data, error, isLoading };
    }
    
  2. useDarkMode – Toggling Dark Mode: Here’s an example of a composable that handles dark mode preference. It manages the state and applies the correct class to the root element.

    import { ref } from 'vue';
    
    export function useDarkMode() {
      const isDarkMode = ref(false);
    
      const toggleDarkMode = () => {
        isDarkMode.value = !isDarkMode.value;
        document.body.classList.toggle('dark', isDarkMode.value);
      };
    
      return { isDarkMode, toggleDarkMode };
    }
    
  3. useAuth – Handling Authentication: For an authentication flow, a composable can manage the user state, token, and handle login/logout actions.

    import { ref } from 'vue';
    
    export function useAuth() {
      const user = ref(null);
      const token = ref(localStorage.getItem('token'));
    
      const login = (username, password) => {
        // Simulate an API call
        user.value = { username };
        token.value = 'fake-token';
        localStorage.setItem('token', token.value);
      };
    
      const logout = () => {
        user.value = null;
        token.value = null;
        localStorage.removeItem('token');
      };
    
      return { user, token, login, logout };
    }
    

When Should You Use a Composable?

Composables are especially useful in the following scenarios:

  1. When You Need to Share Logic Between Components: If you're finding yourself copying and pasting the same logic across multiple components, it's a good indicator that you should abstract it into a composable.

  2. When Using Vue 3’s Composition API: Composables are a natural fit with Vue’s Composition API. They provide a more flexible way to structure code compared to Vue 2’s Options API.

  3. When You Want to Keep Components Clean: If your components are becoming too complex or large, breaking them up into smaller composables helps maintain cleaner and more maintainable code.

  4. When Managing State or Effects: If you need to manage local component state or side effects (e.g., data fetching, subscriptions), composables help keep the logic isolated and reusable.

  5. For Handling Reusable UI Logic: Composables can help in managing UI logic that is reused across various components, such as handling form validation, user input management, or responsive design adjustments.


Composables vs Mixins: What’s the Difference?

While both composables and mixins allow for the reuse of logic, they differ significantly in terms of flexibility and maintainability:

  1. Composables (Vue 3):

    • More explicit: You can choose exactly what to return from the composable.

    • No name collisions: Composables don’t introduce global properties or functions into the component instance, avoiding name conflicts.

    • Better support for Vue's reactivity system: Composables fully leverage Vue’s Composition API.

    • Easier to test: You can test composables in isolation as they’re just functions.

  2. Mixins (Vue 2):

    • Implicit behavior: Logic is automatically merged into the component instance, which can be confusing and harder to trace.

    • Potential name collisions: Because mixins inject properties or methods into the component, there’s a risk of name conflicts.

    • Less modular: Mixins may contain logic that's difficult to extract or reuse in a clean way.


Common Mistakes When Using Composables

Here are some common mistakes developers make when using composables:

  1. Overcomplicating Composables: A composable should focus on a single task. Avoid making composables that do too much, as they become harder to maintain and reuse.

  2. Not Returning Necessary Properties: Ensure that the data or methods your component needs from the composable are included in the return object. If you forget, your component will break or require additional logic to retrieve the data.

  3. Breaking Reusability: Composables should be general-purpose and reusable. Don’t tie them too closely to a specific component, as it reduces their ability to be reused in other parts of the application.

  4. Not Leveraging Vue's Reactivity: Make sure that your composables take full advantage of Vue’s reactive features, such as ref, reactive, and computed. Neglecting these can lead to inefficiency and bugs.

  5. Not Handling Side Effects Properly: Side effects, like API calls, should be handled in a composable, but they need to be done carefully to avoid unexpected behavior. Always return a loading or error state to the component.

Conclusion

Composables in Vue.js are a game-changer for organizing and reusing logic. They help keep components clean and make your codebase more scalable.

 

FAQ Section (Add as <details> or structured FAQ schema)

Q: What is a composable function in Vue.js?

A composable is a reusable function that uses Vue 3's Composition API features like ref, reactive, and watch to encapsulate and share logic across components.

Q: Are composables better than mixins in Vue?

Yes. Composables avoid the issues of name collision and unclear origins that mixins often introduce. They are more explicit and modular.

Q: Can I use composables with Vue 2?

Only with the @vue/composition-api plugin, which backports Composition API features to Vue 2.

Q: What are some common composables?

Examples: useFetch, useDarkMode, useAuth, useForm, useCounter.

Tags

Do you Like?