Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-03-13 03:09:34 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-03-13 03:09:34 +0300
commit3cd08f4bf96cda3e9d3abf233095107832b17c20 (patch)
treedc09a618783a79d70f2a404374d4b850ccf9cc84 /doc/development/fe_guide
parentdd4bee69b7d55620f7dc9db8c36b478bd4959755 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'doc/development/fe_guide')
-rw-r--r--doc/development/fe_guide/graphql.md128
1 files changed, 128 insertions, 0 deletions
diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md
index d21c937bfe4..4a8fca3075b 100644
--- a/doc/development/fe_guide/graphql.md
+++ b/doc/development/fe_guide/graphql.md
@@ -258,6 +258,134 @@ export default {
};
```
+### Working with pagination
+
+GitLab's GraphQL API uses [Relay-style cursor pagination](https://www.apollographql.com/docs/react/data/pagination/#cursor-based)
+for connection types. This means a "cursor" is used to keep track of where in the data
+set the next items should be fetched from.
+
+Every connection type (for example, `DesignConnection` and `DiscussionConnection`) has a field `pageInfo` that contains an information required for pagination:
+
+```javascript
+pageInfo {
+ endCursor
+ hasNextPage
+ hasPreviousPage
+ startCursor
+}
+```
+
+Here:
+
+- `startCursor` and `endCursor` display the cursor of the first and last items
+ respectively.
+- `hasPreviousPage` and `hasNextPage` allow us to check if there are more pages
+ available before or after the current page.
+
+When we fetch data with a connection type, we can pass cursor as `after` or `before`
+parameter, indicating a starting or ending point of our pagination. They should be
+followed with `first` or `last` parameter respectively to indicate _how many_ items
+we want to fetch after or before a given endpoint.
+
+For example, here we're fetching 10 designs after a cursor:
+
+```javascript
+query {
+ project(fullPath: "root/my-project") {
+ id
+ issue(iid: "42") {
+ designCollection {
+ designs(atVersion: null, after: "Ihwffmde0i", first: 10) {
+ edges {
+ node {
+ id
+ }
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+#### Using `fetchMore` method in components
+
+When making an initial fetch, we usually want to start a pagination from the beginning.
+In this case, we can either:
+
+- Skip passing a cursor.
+- Pass `null` explicitly to `after`.
+
+After data is fetched, we should save a `pageInfo` object. Let's assume we're storing
+it to Vue component `data`:
+
+```javascript
+data() {
+ return {
+ pageInfo: null,
+ }
+},
+apollo: {
+ designs: {
+ query: projectQuery,
+ variables() {
+ return {
+ // rest of design variables
+ ...
+ first: 10,
+ };
+ },
+ result(res) {
+ this.pageInfo = res.data?.project?.issue?.designCollection?.designs?.pageInfo;
+ },
+ },
+},
+```
+
+When we want to move to the next page, we use an Apollo `fetchMore` method, passing a
+new cursor (and, optionally, new variables) there. In the `updateQuery` hook, we have
+to return a result we want to see in the Apollo cache after fetching the next page.
+
+```javascript
+fetchNextPage() {
+ // as a first step, we're checking if we have more pages to move forward
+ if (this.pageInfo?.hasNextPage) {
+ this.$apollo.queries.designs.fetchMore({
+ variables: {
+ // rest of design variables
+ ...
+ first: 10,
+ after: this.pageInfo?.endCursor,
+ },
+ updateQuery(previousResult, { fetchMoreResult }) {
+ // here we can implement the logic of adding new designs to fetched one (for example, if we use infinite scroll)
+ // or replacing old result with the new one if we use numbered pages
+
+ const newDesigns = fetchMoreResult.project.issue.designCollection.designs;
+ previousResult.project.issue.designCollection.designs.push(...newDesigns)
+
+ return previousResult;
+ },
+ });
+ }
+}
+```
+
+Please note we don't have to save `pageInfo` one more time; `fetchMore` triggers a query
+`result` hook as well.
+
+#### Limitations
+
+Currently, bidirectional pagination doesn't work:
+
+- `hasNextPage` returns a correct value only when we paginate forward using `endCursor`
+ and `first` parameters.
+- `hasPreviousPage` returns a correct value only when we paginate backward using
+ `startCursor` and `last` parameters.
+
+This should be resolved in the scope of the issue
+[Bi-directional Pagination in GraphQL doesn't work as expected](https://gitlab.com/gitlab-org/gitlab/-/issues/208301).
+
### Testing
#### Mocking response as component data