はじめに
UserとPostが1対多で結びついているような状況で、userとpostを一度 に取得することを想定しています。
記事について
graphql-ruby初学者向けの記事を書いています。
関連記事
- graphql-batchでN+1を解消してみた
- 無限ページネーション(現在の記事)
- 個人開発のcodegen.ymlの設定について考えてみた
- ファイルアップロード機能を実装してみた
使用技術
ruby 3.1.2 rails 7.0.3.1 graphql 2.0.13 react 18.2.0 apollo client 3.6.9
バックエンド
module Queries class Users < Queries::BaseQuery type ObjectTypes::UserType.connection_type, null: false def resolve User.all end end end
connection_type
メソッドを付けるだけで完了です!
{ users(first: 3, after: "", before: "") { edges { cursor node{ id name } } pageInfo { hasPreviousPage hasNextPage startCursor endCursor } } }
first
最初の何件を表示するかを設定できます。
after
before
cursorを設定し、どこを基準に取得するかを決めることができます。
例えば下記のGraphiQLの画像を参考に場合、afterにidが1のユーザーのcursor"MQ"を設定すると、idが2のユーザーから表示されることになります。
hasPreviousPage
hasNextPage
前のページの有無、次のページの有無でtrue falseを返します。
フロントエンド
import { relayStylePagination } from "@apollo/client/utilities"; const client = new ApolloClient({ cache: new InMemoryCache({ typePolicies: { Query: { fields: { users: relayStylePagination(), }, }, }, }), link: authLink.concat(httpLink), });
export const Users = () => { const { data: { users } = {}, fetchMore } = useUsersQuery({ variables: { first: 20, }, }); const onClickAddPage = () => { if (users?.pageInfo.hasNextPage) { fetchMore({ variables: { after: users.pageInfo.endCursor, }, }); } }; return ( <> {users?.edges?.map((user) => ( <ul key={user?.node?.id}> <li>{user?.node?.title}</li> </ul> ))} //次のページが存在する時のみもっとみるを表示 {users?.pageInfo.hasNextPage && ( <button onClick={onClickAddPage}>もっとみる</button> )} </> ); };
元々userが20件表示されており、もっとみるボタンで追加のuserを取得し、最初の20件にマージされすることで、合計40件を表示するようにしています。
オフセットベースのページネーションについて考えてみた
Googleブラウザのようなページネーションを実装する時はgem等で実装するのが良い気がしてます。 普通に実装しようと思うとSQLでOFFSETやLIMITを発行することになると思いますが、データ数が増えればパフォーマンスの低下を招きます。 そこでpagyなるgemがありました。データ数が増えても速度はあんまり変わらないみたいなので良さそうでした。 https://github.com/ddnexus/pagy https://ddnexus.github.io/pagy/index#gsc.tab=0
会社の紹介
株式会社 mofmof では一緒に働いてくれるエンジニアを募集しています。 興味のある方は是非こちらのページよりお越しください! https://www.mof-mof.co.jp/ https://www.mof-mof.co.jp/recruit/