Skip to main content

Command Palette

Search for a command to run...

A simple useLoading composable for your Vue 3 projects

Updated
2 min read
A simple useLoading composable for your Vue 3 projects
S

develops awesome software, contributes to OSS, writes tech tips, and loves Vietnamese milk coffee!

Hey guys,

Wanna share with you all a simple Vue composable function that lies in every Vue project of mine 😎.

Please meet the useLoading 🚀 A simple reusable composable that handles loading state flawlessly for you ❤️.

Before "useLoading", before composable

I (and most of us) have been using this kind of approach before composable 🤣

const isLoading = ref(false);

const loadUsers = async () => {
    isLoading.value = true;

    const res = await getUsers().catch(() => undefined)); // catch to avoid throw

    isLoading.value = false;

    users.value = res?.users ?? [];
};

onMounted(loadUsers);

So before when composable wasn't a thing, we likely had to copy/paste to every component that needed the isLoading indicator.

Vue's useLoading composable

With the composable introduced in Vue 3. It allows us to create multiple reusable pieces.

So I created this for my projects this bad boy. useLoading composable is a global one and can be reused everywhere.

// src/composables/useLoading.ts

import { ref } from 'vue';

export const useLoading = (initializedState = false) => {
  const isLoading = ref(initializedState);

  const startLoading = () => {
    isLoading.value = true;
  };

  const stopLoading = () => {
    isLoading.value = false;
  };

  const withLoading = (handler: () => Promise<void>) => async () => {
    if (isLoading.value) {
      return;
    }

    startLoading();

    await handler().catch((err) => console.error(err));

    stopLoading();
  };

  return {
    isLoading,
    startLoading,
    stopLoading,
    withLoading,
  };
};

Default usage

By default, you can manually trigger startLoading and stopLoading, then use isLoading to check the state.

const { isLoading, startLoading, stopLoading } = useLoading();

startLoading();
// do something so long here
stopLoading();

HoF: withLoading

The awesomeness comes from this bad boy 😎. Having a high-order function to wrap our logic/handlers there and it's automatically triggered startLoading on start and stopLoading on finished.

const { isLoading, withLoading } = useLoading();

const loadUsers = withLoading(async () => {
    const res = await getUsers().catch(() => undefined));
    users.value = res.users ?? [];
});

onMounted(loadUsers);

Not to mention, the withLoading will not trigger another call if isLoading === true , thus ensuring we don't dispatch a lot of API calls/handlers/etc by mistake 🛡️.

Moving forward

Not only useLoading, but also there are several cases which you could create as a composable and reuse:

  • useError (error from API, error from FE, etc)

  • useValidation (simple frontend validation)

  • useRouteParams (return the Vue's router params in strict types)

  • useRouteSearchParams (same as above but for URL Search Params aka GET params)

  • and many more...

Closing topic

And that's that, I hope you will like the useLoading composable. I really like the HoF withLoading above.

Thanks for reading!

More from this blog

S

Seth Phat Tech Blog

69 posts

develops awesome software, contributes to OSS, writes tech tips, and loves Vietnamese milk coffee!