Skip to main content

Pagination

By using some directives and hooks, you can paginate with less code while making efficient API requests.

Here is an example component. Let's implement it using this component.

src/List.tsx
import { List_PaginationQueryDocument, List_UserFragment } from './generated/graphql';

gql` /* GraphQL */
fragment List_user on User {
id
items(first: $count, after: $cursor) {
edges {
node {
id
name
}
cursor
}
pageInfo {
hasNextPage
endCursor
}
}
}
`;

const List: React.FC<{ user: List_UserFragment; }> = ({ user }) => {
// Retrieve nodes from user
// ...
return (
<>
<div>
{nodes.map((node, i) => {
return (
<div>{node.name}</div>
);
})}
</div>
{/* ... */}
</>
);
};

First, add the following directives: @argumentDefinitions, @refetchable, and @pagination. You may also remove some fields only for pagination, such as pageInfo, from the fragment, as Nau will automatically complete them for you.

fragment List_user on User
@argumentDefinitions(count: { type: "Int", defaultValue: 2 }, cursor: { type: "String" })
@refetchable(queryName: "List_PaginationQuery") {
id
items(first: $count, after: $cursor) @pagination {
edges {
node {
name
}
}
}
}

Run graphql-codegen.

yarn graphql-codegen

You can easily implement pagination using the generated List_PaginationQueryDocument with usePagination.

src/List.tsx
import { usePagination } from '@kazekyo/nau';
import { List_PaginationQueryDocument, List_UserFragment } from './generated/graphql';

gql` /* GraphQL */
fragment List_user on User
@argumentDefinitions(count: { type: "Int", defaultValue: 2 }, cursor: { type: "String" })
@refetchable(queryName: "List_PaginationQuery") {
id
items(first: $count, after: $cursor) @pagination {
edges {
node {
name
}
}
}
}
`;

const List: React.FC<{ user: List_UserFragment; }> = ({ user }) => {
const { nodes, hasNext, loadNext, isLoading } = usePagination(List_PaginationQueryDocument, {
id: user.id,
connection: user.items,
});

return (
<>
<div>
{nodes.map((node, i) => {
return (
<div>{node.name}</div>
);
})}
</div>
{hasNext && (
<Button
onClick={() => loadNext(2)}
disabled={!hasNext}
isLoading={isLoading}
>
Load more
</Button>
)}
</>
);
};

Note that whether you are using Nau or not, remember that you must have pagination configured in your cache.

src/index.tsx
import { relayStylePagination } from '@apollo/client/utilities';

const client = new ApolloClient({
cache: new InMemoryCache({
addTypename: true,
possibleTypes: introspectionResult.possibleTypes,
typePolicies: withCacheUpdater({
User: {
fields: {
items: relayStylePagination(),
},
},
}),
}),
link: splitLink,
});