はじめに
NestJS x GraphQLで実装したユーザー一覧を取得するAPIにページング機能をつけてNext.js x URQLで呼び出そうとしたらうまくいかなかったので躓いたところを記録として残しておきます。
この記事が同様の問題で悩んでいる人の助けになれば嬉しいです。
TL;DR
- この解決方法はGraphQLのPaginationを
Cursor-based pagination
で実装した方に有効です - Request, ResponseパラメータはGraphQL Cursor Connections Specificationに従いましょう
環境
ツール・ライブラリ | 用途 | バージョン |
---|---|---|
Next.js | フロントエンドとして利用 | 12.1.0 |
NestJS | サーバーサイドとして利用 | 8.0.0 |
GraphQL Code Generator | コード自動生成ツール | 2.6.2 |
URQL | GraphQL Clientのライブラリ | 2.2.0 |
node.js | フロント、サーバーサイドの実行環境 | v16.14.0 |
ページネーションの方式 | Cursor-based pagination |
課題
NestJSで作ったページネーションをgraphql code gen x URQLを使ってWeb側で表示するような実装をしようとしていました。
基本的な書き方は以下を参考にしたのですが、いざ自分の環境でも再現させようとすると追加のn件を取得することができませんでした。
見ての通り、Fetch moreをクリックしても次のn件が表示されません。
その時に設定していたリクエストパラメータは以下になります
query Users($paginatedUsersInput: PaginatedUsersInput) {
users(paginatedUsersInput: $paginatedUsersInput) {
...paginatedUsers
}
}
fragment paginatedUsers on PaginatedUsersOutput {
edges {
node {
...userProfile
}
}
pageInfo {
endCursor
hasNext
}
}
fragment userProfile on UserOutput {
nickname
uid
}
{
edges: {
node: User
}
pageInfo: {
endCursor: string
hasNext: boolean
}
}
解決方法
InputとOutputをGraphQL Cursor Connections Specificationに合わせることで解決することができました。
実際に変えてみたコードがこちら↓
# paginatedUsersInputを除外してfirst, afterだけにする
query Users($first: Int, $after: String) {
users(first: $first, after: $after) {
...paginatedUsers
}
}
fragment userProfile on UserOutput {
# ~~ 省略 ~~
{
edges: {
// cursorを追加
cursor: string
node: User
}
pageInfo: {
endCursor: string
// hasNextからhasNextPageに変更
hasNextPage: boolean
}
}
無事正常にFetchMoreができました!
注意点
今回採用したページネーションの方式はCursor-based
であって、Offset-based
やTime-based
には適用できないので注意してください。
余談
ページングの実装をしたことがなかったので今回理解しながら書けるようになれて良かったです!
引き続き開発を続けていこうと思います!
ではまた!
参考記事