GraphQL codegen
クエリの作成
import { gql } from '@apollo/client' export const GET_USERS = gql` query GetUsers { users(order_by: { created_at: desc }) { id name created_at } } ` export const GET_USERS_LOCAL = gql` query GetUsers { users(order_by: { created_at: desc }) @client { id name created_at } } ` export const GET_USERIDS = gql` query GetUserIds { users(order_by: { created_at: desc }) { id } } ` export const GET_USERBY_ID = gql` query GetUserById($id: uuid!) { users_by_pk(id: $id) { id name created_at } } ` export const CREATE_USER = gql` mutation CreateUser($name: String!) { insert_users_one(object: { name: $name }) { id name created_at } } ` export const DELETE_USER = gql` mutation DeleteUser($id: uuid!) { delete_users_by_pk(id: $id) { id name created_at } } ` export const UPDATE_USER = gql` mutation UpdateUser($id: uuid!, $name: String!) { update_users_by_pk(pk_columns: { id: $id }, _set: { name: $name }) { id name created_at } } `
@clientでGraphQLサーバーではなく、クライアントのキャッシュから取得できる
export const GET_USERS_LOCAL = gql` query GetUsers { users(order_by: { created_at: desc }) @client { id name created_at } } `
$id 引数でidを渡してデータを取得する
export const GET_USERBY_ID = gql` query GetUserById($id: uuid!) { users_by_pk(id: $id) { id name created_at } } `
CreateUser($name: String!)
$name: クエリの引数を変数化
String: 変数の型定義
!: 必須
export const CREATE_USER = gql` mutation CreateUser($name: String!) { insert_users_one(object: { name: $name }) { id name created_at } } `
型の自動生成
yarn gen-types
キャッシュを使ってグローバルなステートの管理を実現。
Queryを発行し、GraphQLサーバからデータを取得
Apollo Clientは取得したデータを自動的にキャッシュに保存する
そのためクライアントサイドでは他のコンポーネントから
同じクエリで@clientをつけるだけで保存されているキャッシュへアクセスできる
ローカルのステートマネジメント
makeVar(userReacticeVar)を標準で提供している
const createApolloClient = () => { return new ApolloClient({ // window === 'undefined' ブラウザではない = サーバーサイドで処理が走る場合 ssrMode: typeof window === 'undefined', link: new HttpLink({ uri: '', }), cache: new InMemoryCache(), }) } export const initializeApollo = (initialState = null) => { const _apolloClient = apolloClient ?? createApolloClient() // For SSG and SSR always create a new Apollo Client if (typeof window === 'undefined') return _apolloClient // Create the Apollo Client once in the client if (!apolloClient) apolloClient = _apolloClient return _apolloClient }
import { ApolloProvider } from '@apollo/client' import { AppProps } from 'next/app' import { initializeApollo } from '../lib/apolloClient' import '../styles/globals.css' function MyApp({ Component, pageProps }: AppProps) { const client = initializeApollo() return ( <ApolloProvider client={client}> <Component {...pageProps} /> </ApolloProvider> ) } export default MyApp
import Link from 'next/link' import { useQuery } from '@apollo/client' import { GET_USERS } from '../queries/queries' import { GetUsersQuery } from '../types/generated/graphql' import { Layout } from '../components/Layout' const FetchMain = () => { // useQueryの引数には実行したいクエリのコマンドを入れる // ジェネリクスでGetUsersQueryのデータ型定義 const { data, error } = useQuery<GetUsersQuery>(GET_USERS, { // useQueryが実行される度にGraphQLサーバに毎回アクセスする。最新のデータを取得しキャッシュに格納してくれる。 fetchPolicy: 'network-only', // 通信中はキャッシュにあるデータを表示し最新のデータが取得できたら上書きする // fetchPolicy: 'cache-and-network', // 初回のデータ取得以降はキャッシュのデータを表示する。デフォルトではcache-firstが利用される。 // fetchPolicy: 'cache-first', // キャッシュを利用しない // fetchPolicy: 'no-cache', }) if (error) return ( <Layout title="Hasura fetchPolicy"> <p>Error: {error.message}</p> </Layout> ) return ( <Layout title="Hasura fetchPolicy"> <p className="mb-6 font-bold">Hasura main page</p> {data?.users.map((user) => { return ( <p className="my-1" key={user.id}> {user.name} </p> ) })} <Link href="/hasura-sub"> <a className="mt-6">Next</a> </Link> </Layout> ) } export default FetchMain