Skip to content

Commit 3351760

Browse files
committed
docs: data fetching
1 parent 8ebcc3c commit 3351760

File tree

1 file changed

+53
-68
lines changed

1 file changed

+53
-68
lines changed

docs/en/advanced/data-fetching.md

Lines changed: 53 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,37 @@
11
# Data Fetching
22

3-
Sometimes you need to fetch data from the server before rendering a route. For
4-
example, before visiting a user profile, you have to fetch his data from the
5-
server. We can achieve this in two different ways. Each way provide a different
6-
UX approach and both of them are valid designs.
3+
Sometimes you need to fetch data from the server when a route is activated. For example, before rendering a user profile, you need to fetch the user's data from the server. We can achieve this in two different ways:
74

5+
- **Fetching After Navigation**: perform the navigation first, and fetch data in the incoming component's lifecycle hook. Display a loading state while data is being fetched.
86

9-
## Fetching before navigation
7+
- **Fetching Before Navigation**: Fetch data before navigation in the route enter guard, and perform the navigation after data has been fetched.
108

11-
This method consists on fetching the data before actually navigating to the new
12-
route. For those using vue-router 1, this works as the `activate` hook. In
13-
vue-router 2 you use the `beforeRouteEnter` hook to control the navigation flow.
14-
You get access to the `route`, a `redirect` function and a `next` callback to
15-
let the navigation end. Not calling the `next` callback will simply cancel the
16-
navigation. Note that this hook is
9+
Technically, both are valid choices - it ultimately depends on the user experience you are aiming for.
10+
11+
## Fetching After Navigation
12+
13+
When using this approach, we navigate and render the incoming component immediately, and fetch data in the component's `created` hook. It gives us the opportunity to display a loading state while the data is being fetched over the network, and we can also handle loading differently for each view.
14+
15+
Let's assume we have a `Post` component that needs to fetch the data for a post based on `$route.params.id`:
16+
17+
``` html
18+
<template>
19+
<div class="post">
20+
<div class="loading" v-if="loading">
21+
Loading...
22+
</div>
23+
24+
<div v-if="error" class="error">
25+
{{ error }}
26+
</div>
27+
28+
<div v-if="post" class="content">
29+
<h2>{{ post.title }}</h2>
30+
<p>{{ post.body }}</p>
31+
</div>
32+
</div>
33+
</template>
34+
```
1735

1836
``` js
1937
export default {
@@ -24,75 +42,63 @@ export default {
2442
error: null
2543
}
2644
},
27-
beforeRouteEnter (route, redirect, next) {
45+
created () {
2846
// fetch the data when the view is created and the data is
2947
// already being observed
30-
this.fetchData(route.params.id, next)
48+
this.fetchData()
3149
},
3250
watch: {
3351
// call again the method if the route changes
34-
$route () {
35-
this.fetchData(this.$route.params.id)
36-
}
52+
'$route': 'fetchData'
3753
},
3854
methods: {
39-
fetchData (id, cb) {
55+
fetchData () {
4056
this.error = this.post = null
4157
this.loading = true
42-
getPost(id, (err, post) => {
58+
// replace getPost with your data fetching util / API wrapper
59+
getPost(this.$route.params.id, (err, post) => {
4360
this.loading = false
4461
if (err) {
4562
this.error = err.toString()
4663
} else {
4764
this.post = post
4865
}
49-
cb && cb()
5066
})
5167
}
5268
}
5369
}
5470
```
5571

56-
The user still can use the application while the resource is being fetched. It
57-
is therefore recommended to show him with a progress bar or any other indicator
58-
that the web site is waiting for data. If, during this time, the user navigates
59-
somewhere else by clicking on a link, the navigation waiting for data will never
60-
take place.
61-
62-
## Fetching inside the view
72+
## Fetching Before Navigation
6373

64-
This method consists on fetching data during the component lifecycle. It allows
65-
you to define how the content of your view is presented while the resources are
66-
loading. Using this approach let you handle how loading in handled differently
67-
for each view.
68-
69-
Replacing `beforeRouteEnter` with `created` is almost all you need to do to
70-
switch to the other fetching method.
74+
With this approach we fetch the data before actually navigating to the new
75+
route. We can perform the data fetching in the `beforeRouteEnter` guard in the incoming component, and only call `next` when the fetch is complete:
7176

7277
``` js
7378
export default {
7479
data () {
7580
return {
76-
loading: false,
7781
post: null,
7882
error: null
7983
}
8084
},
81-
created () {
82-
// fetch the data when the view is created and the data is
83-
// already being observed
84-
this.fetchData()
85+
beforeRouteEnter (route, redirect, next) {
86+
getPost(route.params.id, (err, post) => {
87+
if (err) {
88+
// display some global error message
89+
} else {
90+
next(vm => {
91+
vm.post = post
92+
})
93+
}
94+
})
8595
},
96+
// when route changes when this component is already rendered,
97+
// the logic will be slightly different.
8698
watch: {
87-
// call again the method if the route changes
88-
'$route': 'fetchData'
89-
},
90-
methods: {
91-
fetchData () {
92-
this.error = this.post = null
93-
this.loading = true
99+
$route () {
100+
this.post = null
94101
getPost(this.$route.params.id, (err, post) => {
95-
this.loading = false
96102
if (err) {
97103
this.error = err.toString()
98104
} else {
@@ -104,25 +110,4 @@ export default {
104110
}
105111
```
106112

107-
The component lifecycle will go on and once the data is fetched, the view will update acordingly. This way you can choose what to show while the data is being fetched. Here we're just displaying _Loading..._:
108-
109-
``` html
110-
<template>
111-
<div class="post">
112-
<div class="loading" v-if="loading">Loading...</div>
113-
<div v-if="error" class="error">
114-
{{ error }}
115-
</div>
116-
<transition name="slide">
117-
<!--
118-
giving the post container a unique key triggers transitions
119-
when the post id changes.
120-
-->
121-
<div v-if="post" class="content" :key="post.id">
122-
<h2>{{ post.title }}</h2>
123-
<p>{{ post.body }}</p>
124-
</div>
125-
</transition>
126-
</div>
127-
</template>
128-
```
113+
The user will stay on the current view while the resource is being fetched for the incoming view. It is therefore recommended to display a progress bar or some kind of indicator while the data is being fetched. If the data fetch fails, it's also necessary to display some kind of global warning message.

0 commit comments

Comments
 (0)