File tree Expand file tree Collapse file tree 7 files changed +55
-23
lines changed Expand file tree Collapse file tree 7 files changed +55
-23
lines changed Original file line number Diff line number Diff line change @@ -2,15 +2,17 @@ import Vue from 'vue'
2
2
import 'es6-promise/auto'
3
3
import { createApp } from './app'
4
4
5
- // a global mixin to invoke fetchData on the client
5
+ // a global mixin that calls `asyncData` when a route component's params change
6
6
Vue . mixin ( {
7
- beforeMount ( ) {
7
+ beforeRouteUpdate ( to , from , next ) {
8
8
const { asyncData } = this . $options
9
9
if ( asyncData ) {
10
- this . dataPromise = asyncData (
11
- this . $store ,
12
- this . $route
13
- )
10
+ asyncData ( {
11
+ store : this . $store ,
12
+ route : to
13
+ } ) . then ( next )
14
+ } else {
15
+ next ( )
14
16
}
15
17
}
16
18
} )
@@ -26,6 +28,17 @@ if (window.__INITIAL_STATE__) {
26
28
// wait until router has resolved all async before hooks
27
29
// and async components...
28
30
router . onReady ( ( ) => {
31
+ // add router hook for handling asyncData
32
+ // doing it after initial route is resolved so that we don't double-fetch
33
+ // the data that we already have.
34
+ router . beforeResolve ( ( to , from , next ) => {
35
+ Promise . all ( router . getMatchedComponents ( to ) . map ( c => {
36
+ if ( c . asyncData ) {
37
+ return c . asyncData ( { store, route : to } )
38
+ }
39
+ } ) ) . then ( next )
40
+ } )
41
+
29
42
// actually mount to DOM
30
43
app . $mount ( '#app' )
31
44
} )
Original file line number Diff line number Diff line change @@ -27,11 +27,11 @@ export default context => {
27
27
// which is resolved when the action is complete and store state has been
28
28
// updated.
29
29
Promise . all ( matchedComponents . map ( component => {
30
- return component . asyncData && component . asyncData (
30
+ return component . asyncData && component . asyncData ( {
31
31
store,
32
- router . currentRoute ,
33
- context
34
- )
32
+ route : router . currentRoute ,
33
+ ssrContext : context
34
+ } )
35
35
} ) ) . then ( ( ) => {
36
36
isDev && console . log ( `data pre-fetch: ${ Date . now ( ) - s } ms` )
37
37
// After all preFetch hooks are resolved, our store is now
Original file line number Diff line number Diff line change @@ -44,6 +44,6 @@ export default {
44
44
FETCH_USER : ( { commit, state } , { id } ) => {
45
45
return state . users [ id ]
46
46
? Promise . resolve ( state . users [ id ] )
47
- : fetchUser ( id ) . then ( user => commit ( 'SET_USER' , { user } ) )
47
+ : fetchUser ( id ) . then ( user => commit ( 'SET_USER' , { id , user } ) )
48
48
}
49
49
}
Original file line number Diff line number Diff line change @@ -17,7 +17,7 @@ export default {
17
17
} )
18
18
} ,
19
19
20
- SET_USER : ( state , { user } ) => {
21
- Vue . set ( state . users , user . id , user )
20
+ SET_USER : ( state , { id , user } ) => {
21
+ Vue . set ( state . users , id , user || false ) /* false means user not found */
22
22
}
23
23
}
Original file line number Diff line number Diff line change @@ -10,9 +10,9 @@ export default function createListView (type) {
10
10
return {
11
11
name : `${ type } -stories-view` ,
12
12
13
- asyncData ( store , route , context ) {
13
+ asyncData ( { store, ssrContext } ) {
14
14
return store . dispatch ( 'FETCH_LIST_DATA' , { type } ) . then ( ( ) => {
15
- setTitle ( camelize ( type ) , context )
15
+ setTitle ( camelize ( type ) , ssrContext )
16
16
} )
17
17
} ,
18
18
Original file line number Diff line number Diff line change @@ -46,20 +46,33 @@ export default {
46
46
}
47
47
},
48
48
49
- asyncData (store , { params: { id }}, context ) {
49
+ // We only fetch the item itself before entering the view, because
50
+ // it might take a long time to load threads with hundreds of comments
51
+ // due to how the HN Firebase API works.
52
+ asyncData ({ store, route: { params: { id }}, ssrContext }) {
50
53
return store .dispatch (' FETCH_ITEMS' , { ids: [id] }).then (() => {
51
54
const item = store .state .items [id]
52
- setTitle (item .title , context )
55
+ setTitle (item .title , ssrContext )
53
56
})
54
57
},
55
58
56
- // on the client, fetch all comments
59
+ // Fetch comments when mounted on the client
57
60
beforeMount () {
58
- this .dataPromise .then (() => {
61
+ this .fetchComments ()
62
+ },
63
+
64
+ // refetch comments if item changed
65
+ watch: {
66
+ item: ' fetchComments'
67
+ },
68
+
69
+ methods: {
70
+ fetchComments () {
71
+ this .loading = true
59
72
fetchComments (this .$store , this .item ).then (() => {
60
73
this .loading = false
61
74
})
62
- })
75
+ }
63
76
}
64
77
}
65
78
Original file line number Diff line number Diff line change 1
1
<template >
2
2
<div class =" user-view" >
3
- <spinner :show =" !user " ></spinner >
3
+ <spinner :show =" !userLoaded " ></spinner >
4
4
<template v-if =" user " >
5
5
<h1 >User : {{ user.id }}</h1 >
6
6
<ul class =" meta" >
13
13
<a :href =" 'https://news.ycombinator.com/threads?id=' + user.id" >comments</a >
14
14
</p >
15
15
</template >
16
+ <template v-else-if =" user === false " >
17
+ <h1 >User not found.</h1 >
18
+ </template >
16
19
</div >
17
20
</template >
18
21
@@ -27,13 +30,16 @@ export default {
27
30
computed: {
28
31
user () {
29
32
return this .$store .state .users [this .$route .params .id ]
33
+ },
34
+ userLoaded () {
35
+ return this .$route .params .id in this .$store .state .users
30
36
}
31
37
},
32
38
33
- asyncData (store , { params: { id }}, context ) {
39
+ asyncData ({ store, route : { params: { id }}, ssrContext } ) {
34
40
return store .dispatch (' FETCH_USER' , { id }).then (() => {
35
41
const user = store .state .users [id]
36
- setTitle (user .id , context )
42
+ setTitle (user ? user .id : ' User not found ' , ssrContext )
37
43
})
38
44
}
39
45
}
You can’t perform that action at this time.
0 commit comments