Skip to content

Commit 0e81adc

Browse files
evanyeungfacebook-github-bot
authored andcommitted
Rewrite the pagination docs and remove pagination from the tutorial
Reviewed By: captbaritone Differential Revision: D79768707 fbshipit-source-id: 3854e1628aafa531dcb4aa463ef549e5db64c038
1 parent 73d99b9 commit 0e81adc

File tree

5 files changed

+222
-649
lines changed

5 files changed

+222
-649
lines changed
Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
id: connections
3-
title: Connections
3+
title: Why Connections?
44
slug: /guided-tour/list-data/connections/
55
description: Relay guide for connections
66
keywords:
@@ -9,15 +9,73 @@ keywords:
99
---
1010

1111
import DocsRating from '@site/src/core/DocsRating';
12-
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';
13-
import useBaseUrl from '@docusaurus/useBaseUrl';
1412

15-
There are several scenarios in which we'll want to query a list of data from the GraphQL server. Often times we don't want to query the *entire* set of data up front, but rather discrete sub-parts of the list, incrementally, usually in response to user input or other events. Querying a list of data in discrete parts is usually known as [Pagination](https://graphql.org/learn/pagination/).
13+
# Why Connections?
1614

15+
:::info
16+
For a video format of how the connection spec was derived, check out [Sabrina Wasserman's GraphQL talk](../../guides/graphql-server-specification.md#graphql-conf-talk)!
17+
:::
1718

18-
Specifically in Relay, we do this via GraphQL fields known as [Connections](https://graphql.org/learn/pagination/#complete-connection-model). Connections are GraphQL fields that take a set of arguments to specify which "slice" of the list to query, and include in their response both the "slice" of the list that was requested, as well as information to indicate if there is more data available in the list and how to query it; this additional information can be used in order to perform pagination by querying for more "slices" or pages on the list.
19+
Relay does a lot of the work for you when handling paginated collections of items. But to do that, it relies on a specific convention for how those collections are modeled in your schema. This convention is powerful and flexible, and comes out of experience building many products with collections of items. Let’s step through the design process for this schema convention so that we can understand why it works this way.
1920

20-
More specifically, we perform *cursor-based pagination,* in which the input used to query for "slices" of the list is a `cursor` and a `count`. Cursors are essentially opaque tokens that serve as markers or pointers to a position in the list. If you're curious to learn more about the details of cursor-based pagination and connections, check out <a href={useBaseUrl('graphql/connections.htm')}>the spec</a>.
21+
There are three important points to understand:
2122

23+
* You may need to model data about an item's inclusion in the collection, such as in a list of friends where you may wish to model the date you friended that person. We handle this by creating nodes that represent the edges, the relationship between the item in the collection and the collection itself.
24+
* The page itself has properties, such as whether or not there is a next page available. We handle this with a node that represents the current page info.
25+
* Pagination is done by *cursors* — opaque symbols that point to the next page of results — rather than offsets.
26+
27+
Imagine we want to show a list of the user’s friends. At a high level, we imagine a graph where the viewer and their friends are each nodes. From the viewer to each friend node is an edge, and the edge itself has properties.
28+
29+
![Conceptual graph with properties on its edges](/img/docs/tutorial/connections-conceptual-graph.png)
30+
31+
Now let’s try to model this situation using GraphQL.
32+
33+
In GraphQL, only nodes can have properties, not edges. So the first thing we’ll do is represent the conceptual edge from you to your friend with its very own node.
34+
35+
![Edge properties modeled using nodes that represent the edges](/img/docs/tutorial/connections-edge-nodes.png)
36+
37+
Now the properties of the edge are represented by a new type of node called a “`FriendsEdge`”.
38+
39+
The GraphQL to query this would like this:
40+
41+
```
42+
// XXX example only, not final code
43+
fragment FriendsFragment1 on Viewer {
44+
friends {
45+
since // a property of the edge
46+
node {
47+
name // a property of the friend itself
48+
}
49+
}
50+
}
51+
```
52+
53+
Now we have a good place in the GraphQL schema to put edge-specific information such as the date when the edge was created (that is, the date you friended that person).
54+
55+
* * *
56+
57+
Now consider what we would need to model in our schema in order to support pagination and infinite scrolling.
58+
59+
* The client must be able to specify how large of a page it wants.
60+
* The client must be informed as to whether any more pages are available, so that it can enable or disable the ‘next page’ button (or, for infinite scrolling, can stop making further requests).
61+
* The client must be able to ask for the next page after the one it already has.
62+
63+
How can we use the features of GraphQL to do these things? Specifying the page size is done with field arguments. In other words, instead of just `friends` the query will say `friends(first: 3)`, passing the page size as an argument to the `friends` field.
64+
65+
For the server to say whether there is a next page or not, we need to introduce a node in the graph that has information about the *list of friends itself,* just like we are introducing a node for each edge to store information about the edge itself. This new node is called a *Connection*.
66+
67+
The Connection node represents the connection itself between you and your friends. Metadata about the connection is stored there — for example, it could have a `totalCount` field that says how many friends you have. In addition, it always has two fields which represent the *current* page: a `pageInfo` field with metadata about the current page, such as whether there is another page available — and an `edges` field that points to the edges we saw before:
68+
69+
![The full connection model with page info and edges](/img/docs/tutorial/connections-full-model.png)
70+
71+
Finally, we need a way to request the next page of results. You’ll notice in the above diagram that the `PageInfo` node has a field called `lastCursor`. This is an opaque token provided by the server that represents the position in the list of the last edge that we were given (the friend “Charmaine”). We can then pass this cursor back to the server in order to retrieve the next page.
72+
73+
By passing the `lastCursor` value back to the server as an argument to the `friends` field, we can ask the server for friends that are *after* the ones we’ve already retrieved:
74+
75+
![After fetching the next page of results](/img/docs/tutorial/connections-full-model-next-page.png)
76+
77+
This overall scheme for modeling paginated lists is specified in detail in the [GraphQL Cursor Connections Spec](https://relay.dev/graphql/connections.htm). It is flexible for many different applications, and although Relay relies on this convention to handle pagination automatically, designing your schema this way is a good idea whether or not you use Relay.
78+
79+
Now that we've stepped through the underlying model for Connections, let’s turn our attention to actually using it to implement Comments for our Newsfeed stories.
2280

2381
<DocsRating />

0 commit comments

Comments
 (0)