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!