# A simple useLoading composable for your Vue 3 projects

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 🤣

```typescript
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](https://vuejs.org/guide/reusability/composables) 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.

```typescript
// 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.

```typescript
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.

```typescript
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!
