forked from vercel/next.js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
PostList.js
121 lines (114 loc) · 3.02 KB
/
PostList.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import { useQuery } from '@apollo/react-hooks'
import { NetworkStatus } from 'apollo-client'
import gql from 'graphql-tag'
import ErrorMessage from './ErrorMessage'
import PostUpvoter from './PostUpvoter'
export const ALL_POSTS_QUERY = gql`
query allPosts($first: Int!, $skip: Int!) {
allPosts(orderBy: createdAt_DESC, first: $first, skip: $skip) {
id
title
votes
url
createdAt
}
_allPostsMeta {
count
}
}
`
export const allPostsQueryVars = {
skip: 0,
first: 10,
}
export default function PostList() {
const { loading, error, data, fetchMore, networkStatus } = useQuery(
ALL_POSTS_QUERY,
{
variables: allPostsQueryVars,
// Setting this value to true will make the component rerender when
// the "networkStatus" changes, so we are able to know if it is fetching
// more data
notifyOnNetworkStatusChange: true,
}
)
const loadingMorePosts = networkStatus === NetworkStatus.fetchMore
const loadMorePosts = () => {
fetchMore({
variables: {
skip: allPosts.length,
},
updateQuery: (previousResult, { fetchMoreResult }) => {
if (!fetchMoreResult) {
return previousResult
}
return Object.assign({}, previousResult, {
// Append the new posts results to the old one
allPosts: [...previousResult.allPosts, ...fetchMoreResult.allPosts],
})
},
})
}
if (error) return <ErrorMessage message="Error loading posts." />
if (loading && !loadingMorePosts) return <div>Loading</div>
const { allPosts, _allPostsMeta } = data
const areMorePosts = allPosts.length < _allPostsMeta.count
return (
<section>
<ul>
{allPosts.map((post, index) => (
<li key={post.id}>
<div>
<span>{index + 1}. </span>
<a href={post.url}>{post.title}</a>
<PostUpvoter id={post.id} votes={post.votes} />
</div>
</li>
))}
</ul>
{areMorePosts && (
<button onClick={() => loadMorePosts()} disabled={loadingMorePosts}>
{loadingMorePosts ? 'Loading...' : 'Show More'}
</button>
)}
<style jsx>{`
section {
padding-bottom: 20px;
}
li {
display: block;
margin-bottom: 10px;
}
div {
align-items: center;
display: flex;
}
a {
font-size: 14px;
margin-right: 10px;
text-decoration: none;
padding-bottom: 0;
border: 0;
}
span {
font-size: 14px;
margin-right: 5px;
}
ul {
margin: 0;
padding: 0;
}
button:before {
align-self: center;
border-style: solid;
border-width: 6px 4px 0 4px;
border-color: #ffffff transparent transparent transparent;
content: '';
height: 0;
margin-right: 5px;
width: 0;
}
`}</style>
</section>
)
}