Skip to content

Data Loaders

Data loaders streamline any asynchronous state management with Vue Router, like Data Fetching. Adopting Data loaders ensures a consistent and efficient way to manage data fetching in your application. Keep all the benefits of using libraries like Pinia Colada or Apollo and integrate them seamlessly with client-side navigation.

This is achieved by extracting the loading logic outside of the component setup (unlike <Suspense>). This way, the loading logic can be executed independently of the component lifecycle, and the component can focus on rendering the data. Data Loaders are automatically collected and awaited within a navigation guard, ensuring the data is ready before rendering the component.

Features

  • Parallel data fetching and deduplication
  • Automatic loading state management
  • Error handling
  • Extensible by loader implementations
  • SSR support
  • Prefetching data support

Installation

After installing unplugin-vue-router, install the DataLoaderPlugin before the router.

ts
import { 
createApp
} from 'vue'
import {
routes
} from 'vue-router/auto-routes'
import {
createRouter
,
createWebHistory
} from 'vue-router'
import {
DataLoaderPlugin
} from 'unplugin-vue-router/data-loaders'
const
router
=
createRouter
({
history
:
createWebHistory
(),
routes
,
}) const
app
=
createApp
({})
// Register the plugin before the router
app
.
use
(
DataLoaderPlugin
, {
router
})
// adding the router will trigger the initial navigation
app
.
use
(
router
)
app
.
mount
('#app')

Quick start

There are different data loaders implementation, the most simple one is the Basic Loader which always reruns data fetching. A more efficient one, is the Colada Loader which uses @pinia/colada under the hood. In the following examples, we will be using the basic loader.

Loaders are composables defined through a defineLoader function like defineBasicLoader or defineColadaLoader. They are used in the component setup to extract the needed information.

To get started, define and export a loader from a page:

vue
<script lang="ts">
import { 
defineBasicLoader
} from 'unplugin-vue-router/data-loaders/basic'
import {
getUserById
} from '../api'
export const
useUserData
=
defineBasicLoader
('/users/[id]', async (
route
) => {
return
getUserById
(
route
.
params
.
id
)
}) </script> <script setup lang="ts"> const {
data
:
user
, // the data returned by the loader
isLoading
, // a boolean indicating if the loader is fetching data
error
, // an error object if the loader failed
reload
, // a function to refetch the data without navigating
} =
useUserData
()
</script> <template> <
main
>
<
p
v-if="
isLoading
">Loading...</
p
>
<template v-else-if="
error
">
<
p
>{{
error
.message }}</
p
>
<
button
@
click
="
reload
()">Retry</
button
>
</template> <template v-else> <
p
>{{
user
}}</
p
>
</template> </
main
>
</template>

The loader will automatically run when the route changes, for example when navigating to /users/1, even when coming from /users/2, the loader will fetch the data and delay the navigation until the data is ready.

On top of that, you are free to reuse the returned composable useUserData in any other component, and it will automatically share the same data fetching instance.

Why Data Loaders?

Data fetching is the most common need for a web application. There are many ways of handling data fetching, and they all have their pros and cons. Data loaders are a way to streamline data fetching in your application. Instead of forcing you to choose between different libraries, data loaders provide a consistent way to manage data fetching in your application no matter the underlying library or strategy you use.

Released under the MIT License.