Skip to content

Commit 2140f52

Browse files
committed
docs: common
1 parent 891b5ed commit 2140f52

File tree

1 file changed

+94
-3
lines changed

1 file changed

+94
-3
lines changed

docs/data-loaders/introduction.md

Lines changed: 94 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,99 @@
1-
# Introduction
1+
# Defining Data Loaders
22

3-
## Defining a Loader
3+
In order to use data loaders, you need to define them first. Data loaders themselves are the composables returned by the different `defineLoader` functions. Each loader definition is specific to the `defineLoader` function used. For example, `defineBasicLoader` expects an async function as the first argument while `defineColadaLoader` expects an object with a `query` function. All loaders should allow to pass an async function that can throw errors, and `NavigationResult`.
44

5-
Should not contain any side-effects besides the data fetching.
5+
Any composables returned by _any_ `defineLoader` function share the same signature:
6+
7+
```vue twoslash
8+
<script lang="ts">
9+
import 'unplugin-vue-router/client'
10+
import './typed-router.d'
11+
// ---cut---
12+
import { defineBasicLoader } from 'unplugin-vue-router/data-loaders/basic'
13+
import { getUserById } from '../api'
14+
15+
export const useUserData = defineBasicLoader('/users/[id]', async (route) => {
16+
return getUserById(route.params.id)
17+
})
18+
</script>
19+
20+
<script setup lang="ts">
21+
// hello // [!code focus:7]
22+
const {
23+
data: user, // the data returned by the loader
24+
isLoading, // a boolean indicating if the loader is fetching data
25+
error, // an error object if the loader failed
26+
reload, // a function to refetch the data without navigating
27+
} = useUserData()
28+
</script>
29+
```
30+
31+
**But they are not limited by it!** For example, the `defineColadaLoader` function returns a composable with a few more properties like `status` and `refresh`. Because of this it's important to refer to the documentation of the specific loader you are using.
32+
33+
This page will guide you through the **foundation** of defining data loaders, no matter their implementation.
34+
35+
## The loader function
36+
37+
The loader function is the _core_ of data loaders. They are asynchronous functions that return the data you want to expose in the `data` property of the returned composable.
38+
39+
### The `to` argument
40+
41+
The `to` argument represents the location object we are navigating to. It should be used as the source of truth for all data fetching parameters.
42+
43+
```ts twoslash
44+
import 'unplugin-vue-router/client'
45+
import './typed-router.d'
46+
import { defineBasicLoader } from 'unplugin-vue-router/data-loaders/basic'
47+
import { getUserById } from '../api'
48+
// ---cut---
49+
export const useUserData = defineBasicLoader('/users/[id]', async (to) => {
50+
const user = await getUserById(to.params.id)
51+
// here we can modify the data before returning it
52+
return user
53+
})
54+
```
55+
56+
By using the route location to fetch data, we ensure a consistent relationship between the data and the URL, **improving the user experience**.
57+
58+
### Side effects
59+
60+
It's important to avoid side effects in the loader function. Don't call `watch`, or create reactive effects like `ref`, `toRefs()`, `computed`, etc.
61+
62+
## Accessing Global Properties
63+
64+
In the loader function, you can access global properties like the router instance, a store, etc. This is because using `inject()` within the loader function **is possible**. Since loaders are asynchronous, make sure you are using the `inject` function **before any `await`**:
65+
66+
```ts twoslash
67+
import 'unplugin-vue-router/client'
68+
import './typed-router.d'
69+
import { defineBasicLoader } from 'unplugin-vue-router/data-loaders/basic'
70+
import { getUserById } from '../api'
71+
// ---cut---
72+
import { inject } from 'vue'
73+
import { useSomeStore } from '@/stores'
74+
75+
export const useUserData = defineBasicLoader('/users/[id]', async (to) => {
76+
// ✅ This will work
77+
const injectedValue = inject('key') // [!code ++]
78+
const store = useSomeStore() // [!code ++]
79+
80+
const user = await getUserById(to.params.id)
81+
// ❌ These won't work
82+
const injectedValue2 = inject('key') // [!code error]
83+
const store2 = useSomeStore() // [!code error]
84+
// ...
85+
return user
86+
})
87+
```
88+
89+
<!--
90+
Why doesn't this work?
91+
// @error: Custom error message
92+
-->
93+
94+
## Options
95+
96+
All
697

798
## Connecting a loader to a page
899

0 commit comments

Comments
 (0)