mirror of
https://github.com/muerwre/muerwre.github.io.git
synced 2025-04-25 02:46:39 +07:00
added whole content
This commit is contained in:
parent
1b5df685cb
commit
8b25e0631a
70 changed files with 5962 additions and 19 deletions
79
content/GraphQL/Apollo Client pagination.md
Normal file
79
content/GraphQL/Apollo Client pagination.md
Normal file
|
@ -0,0 +1,79 @@
|
|||
Say, we have `gql` response like this and we wan't to have pagination with it. Let's merge it as it specified in [official documentation](https://www.apollographql.com/docs/react/caching/cache-field-behavior/#the-merge-function)
|
||||
|
||||
```graphql
|
||||
query listItems(
|
||||
filter: Filter,
|
||||
sort: String,
|
||||
limit: Number,
|
||||
offset: Number,
|
||||
): ItemList!
|
||||
|
||||
input Filter {
|
||||
name: String!
|
||||
type: String!
|
||||
}
|
||||
|
||||
type ItemList {
|
||||
items: [Item!]!
|
||||
totalCount: Int!
|
||||
}
|
||||
```
|
||||
|
||||
We will setup `ApolloClient` with `typePolicies` to merge incoming data in cache:
|
||||
|
||||
```typescript
|
||||
import { ApolloClient, InMemoryCache } from '@apollo/client';
|
||||
|
||||
const client = new ApolloClient({
|
||||
// ...
|
||||
cache: new InMemoryCache({ typePolicies }),
|
||||
// ...
|
||||
});
|
||||
|
||||
export const typePolicies: TypePolicies = {
|
||||
Query: {
|
||||
fields: {
|
||||
// query name
|
||||
listItems: {
|
||||
// apollo will serialize and use keyArgs as unique
|
||||
// identifier in cache for every query
|
||||
// consider choosing the right fields,
|
||||
// i.e. limit and offset won't work here
|
||||
keyArgs: [
|
||||
'sort', // primitive type
|
||||
'filter', ['name', 'type'] // nested fields of `filter`
|
||||
],
|
||||
merge: mergeItemsWithTotalCount,
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
We will need merge function `mergeItemsWithTotalCount`, which will join results of query and cached data for specific key:
|
||||
|
||||
```typescript
|
||||
/** merges all sources with { items: unknown[], totalCount: number } */
|
||||
const mergeItemsWithTotalCount = (existing, incoming, { args }) => {
|
||||
// no existing data
|
||||
if (!existing || !args?.offset || args.offset < existing.length) {
|
||||
return incoming || [];
|
||||
}
|
||||
|
||||
// If hook was called multiple times
|
||||
if (existing?.items?.length && args?.offset < existing.items.length) {
|
||||
return existing || [];
|
||||
}
|
||||
|
||||
// merge cache and incoming data
|
||||
const items = [...(existing?.items || []), ...(incoming?.items || [])];
|
||||
|
||||
// apply latest result for totalCount
|
||||
const totalCount = incoming?.totalCount || existing?.totalCount;
|
||||
|
||||
return {
|
||||
...(incoming || existing || {}),
|
||||
items,
|
||||
totalCount,
|
||||
};
|
||||
};
|
||||
```
|
Loading…
Add table
Add a link
Reference in a new issue