DEV Community

Cover image for Must-Know Reusable Module Vs Component In Vue 3 Composition API
Raja Tamil
Raja Tamil

Posted on

1

Must-Know Reusable Module Vs Component In Vue 3 Composition API

As a Vue.js developer, we want to keep our code clean and tidy by creating the optimal amount of reusable code.

In Vue 3 with the Composition API, we can absolutely do that by creating reusable JS modules aka hook functions and child components.

So what’s the difference between them?

When do we use one or the other?

Let’s find out!

JavaScript module aka hook function is a great way to separate business logic from the Vue component.

It’s completely reusable and UI independent.

If you’re coming from MVC pattern, this would be M (Model) part of it.

Vue components that are not page-based, meaning no route attached to it, aka Child components, are great when we want to reuse HTML template code aka UI that can be used in multiple parent components.

Now you have a better understanding of not only the differences, but also which one to use when.

I’m going to demonstrate with some example code throughout this article to show cases of when to use them.

Note: This article is intermediate and you should have the basic knowledge of using Vue.js or a similar framework.

Get A List Of Products

I assume you already know how to get Up and Running With Vue JS 3 Project Using Vue CLI.

Let’s say we have a ProductList.vue page-based component in our application handling async operation to get a list of products.

I used Firebase in the example below for the async operations.

I have an article on how to install Firebase to your vue project as well as on how to make Cloud Firestore queries if you’re interested.

First, create a product reactive array and call loadProduct() function inside onMounted() lifecycle method.

Recommended
Must-Know Ref vs Reactive Differences In Vue 3 Composition API

import firebase from "firebase";
import { onMounted, reactive } from "vue";
export default {

  setup() {

    const products = reactive([]);

    onMounted(() => {
      loadProducts();
    });

    const loadProducts = async () {
      try {
        const productsSnap = await firebase
          .firestore()
          .collection("products")
          .orderBy("brand", "asc")
          .get();

        productsSnap.forEach((doc) => {
          let product = doc.data();
          product.id = doc.id;
          products.push(product);
        });

      } catch (e) {
        console.log("Error Loading Products");
      }
    }

    return {
      products,
    };
  },
};
Enter fullscreen mode Exit fullscreen mode

Inside the loadProducts() declaration, use Firebase query to get a list of products that I’ve already stored in the Firebase Cloud Firestore database.

Finally return the products array to use in the template.

Each product object has two keys that are:

  • title
  • upc

Nothing fancy.

This works great!

As the project evolves, let’s say I’ll need to create an inventory component where I want to use a list of products as a drop-down, for example, to select a product to create an inventory from.

I’ll have to rewrite loadProducts() code which I do not want to do.

With Vue 3 Composition API, we can easily extract the async code into a UI-independent JavaScript module and can reuse it wherever we want in our application.

Let’s see how to do that.

Reusable Product.js Module

Create a Product.js file inside the src/modules folder which is where all of my product-related async operations will go such as loadProducts, addProduct, updateProduct, deleteProduct, etc.

Let’s see how to extract the loadProducts() code from the ProductList.vue to Product.js.

Import Firebase as we’ll be using it for CRUD async operations.

Then declare useProduct() function as well as reactive state object inside the function which will have one property in it called products that is a type of array.

import { reactive, toRefs } from "vue";
import firebase from "firebase";

export default function useProduct() {
  const state = reactive({
    products: [],
  });

  const loadProducts = async() => {
    try {
      const productsSnap = await firebase.firestore().collection("products").orderBy("brand", "asc").get();
      productsSnap.forEach(doc => {
        let product = doc.data();
        product.id = doc.id;
        state.products.push(product);
      });
    } catch (e) {
      console.log("Error Loading Products")
    }
  }
  return { ...toRefs(state),
    loadProducts
  }
}
Enter fullscreen mode Exit fullscreen mode

Then, create the loadProducts() function which gets the products data from the products collection in Cloud Firestore and gets the snapshot of it.

Loop through them and push each product into the products array.

Finally, return the state and loadProduct.

The reason I wrapped state with toRefs is to convert the reactive object into a plain JavaScript object so that I can destructure it when needed.

Now we have the Product.js module ready to use inside the ProductList.vue or any component that needs a list of products in our app.

ProductList.vue

Now, we can easily get a list of products like before with just four steps.

First, import the product module at the top.

Secondly, call useProduct() function and destructure products and loadProducts inside the setup() function.

Then, invoke loadProducts() inside the onMounted() lifecycle method.

import { onMounted } from "vue";
import useProduct from "@/modules/product";
export default {
  setup() {
    const { products, loadProducts } = useProduct();
    onMounted(async () => {
      await loadProducts();
    });
    return {
      products,
    };
  },
};
Enter fullscreen mode Exit fullscreen mode

Finally, return the products which is the same as before.

At this stage, products are available in the template to use and we can loop through them using v-for to show however we want.

Recommended
Vue + Firestore ← Build A Simple CRUD App with Authentication

You can see how easy it is to create a module like Product.js to organize reusable UI-independent functionalities. 🙂

One more benefit of using modules like Product.js is to use them as state management as well.

Modules As State Management

To use modules as state management, all we need to do is to declare the state object model outside of the useProduct() function which then becomes a global variable.

import { reactive, toRefs } from "vue";
import firebase from "firebase";

 const state = reactive({
        products: [],
 });

export default function useProduct() {
  ...
}
Enter fullscreen mode Exit fullscreen mode

Continue Reading...

AWS GenAI LIVE image

How is generative AI increasing efficiency?

Join AWS GenAI LIVE! to find out how gen AI is reshaping productivity, streamlining processes, and driving innovation.

Learn more

Top comments (0)

AWS GenAI LIVE image

Real challenges. Real solutions. Real talk.

From technical discussions to philosophical debates, AWS and AWS Partners examine the impact and evolution of gen AI.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay