Apolloメモ
リクエスト
レスポンスに応じたデフォルトの処理をセットする
https://www.apollographql.com/docs/react/networking/advanced-http-networking/#customizing-response-logic
fetch関数を変更する
https://www.apollographql.com/docs/react/networking/advanced-http-networking#custom-fetching
Query
-
手動でデータを取得するにはrefetchを使うか、useLazyQueryを使う。
-
useSuspenseQueryを
<Suspense>
の子コンポーネントで使うと、リクエスト中はfallbackが表示される。 -
<Suspense>
の中に<Suspense>
を入れると各<Suspense>
内でデータを取得すると上位の<Suspense>
でのデータ取得を待つ必要があるので表示が遅くなります。
その場合はuseLoadableQuery、useBackgroundQuery、useReadQueryを使います。リクエストをスキップするにはskipTokenを指定します。 -
Reactのスコープの外やルーターと組み合わせて使う場合はpreloadQueryを使う。
-
取得してデータを変更してはいけない。
Mutation
-
mutationの結果(loading、errors)を初期化したい場合はresetを使う。(キャッシュは初期化されない)
-
サーバのレスポンスではなく、リクエスト内容をキャッシュに反映するには
optimisticResponse
を使う。
Header
-
静的にヘッダーをセットするにはheadersを設定する。
-
動的にヘッダーをセットするにはsetContext()を使う。
Link
-
onErrorはリクエストの後に実行される
-
forwardで次のリンクに移動
-
forwaordの戻り値のmap()でリクエスト後の処理を登録することができる
-
OperationオブジェクトのsetContext()のcontext
キャッシュ
-
クエリとそのパラメータごとにキャッシュされる。
-
同じクエリはキャッシュを利用することができるが、別のクエリで使用するには設定が必要
https://www.apollographql.com/docs/react/caching/advanced-topics/#cache-redirects -
mutationの結果をキャッシュに反映したい場合は、mutationのレスポンスで
__typename
とid
(mutationの戻り値だけではidに対応するデータを取得する目的のキャッシュを変更することはできるが、キャッシュされている配列の中に存在するデータを変更することはできない)を返すか、update関数を定義するか、onQueryUpdatedコールバック関数を定義する。 -
手動でキャッシュを更新したい場合、client.refetchQueries()を使う。
ReactではclientはuseApolloClientで取得する。
キャッシュのキー
-
デフォルトでは
__typename
とid
でデータを特定してキャッシュに反映する。
https://www.apollographql.com/docs/react/why-apollo/#zero-config-caching -
キーに使用するプロパティやキーの生成方法を変更することができる。 https://www.apollographql.com/docs/react/caching/cache-interaction
キャッシュを操作する
以下はクエリのみ操作する。つまり、サーバにリクエストが送信されない。 Apollo ClientはInMemoryCacheをプロキシしている。
クエリで操作
client.readQuery / client.writeQuery / client.updateQuery
-
client.writeQuery
で既存のデータを上書きすることができる。データの一部を渡した場合、その部分のみ上書きされる。 -
updateFragment
とupdateQuery
はデータを取得して、それを基に上書きする処理ができる。
readQuery
キャッシュに対応する値がない場合はnull
を返す。
フラグメントで操作
client.readFragment
/ client.writeFragment
/ client.updateFragment / client.useFragment
手動で操作
cache.identify(obj)はobj
のidを取得する。
refのフィールドにアクセスるにはreadField()
を使う。
useMutationで使用するとサーバへのアクセスなしにキャッシュを変更することができる。
キャッシュからデータを削除する
cache.evict({ id: 'foo-id' })
はidが'foo-id'
のデータをキャッシュから削除します。
cache.gc()
で孤立したデータを削除する。
すべてのキャッシュをクリアするにはclient.clearStore()
を使う。
fetchMore
-
パラメータを無視してクエリ毎にキャッシュするには
typePolicies
を設定する。 -
キャッシュされたデータの取得方法を変更するには
typePolicies
のread
を変更する。
フラグメント
-
フラグメントは再利用可能な型の部分集合
-
以下のように埋め込むことができる
const FooFragment = gql`
fragment FooFragment on Bar {
name
}
`;
const client = new ApolloClient({
uri: 'https://example.com/',
cache: new InMemoryCache({
fragments: createFragmentRegistry(gql`
${UserFragment}
`),
}),
});
-
フラグメントはそれを使うクエリに埋め込むかfragmentsオプションに登録する必要がある。
-
フラグメントをコンポーネントに関連付ける例
-
possibleTypesにinterfaceやunionの親子関係を記述する。
https://the-guild.dev/graphql/codegen/plugins/other/fragment-matcher -
useFragmentを使うとフラグメントに関連したデータを効率的に取得することができます。
type
- 以下のように型のフィールドに引数を渡すことができる
type Car {
id: ID!
name: String!
size(unit: LengthUnit = METER): Float
}
ディレクティブ
GraphQL標準のディレクティブ
https://spec.graphql.org/June2018/#sec-Type-System.Directives
@client
フィールドがローカルに存在するデータであり、そのデータ取得がサーバーへのクエリではなくクライアント側のキャッシュまたはローカルストアから行われることを示すフラグとして機能します。
@connect
@connection
ディレクティブを付与すると、同じクエリでも@connection
ディレクティブに与えられた値毎に別のクエリとして区別されます。これによって、同じクエリで用途に応じて複数の値をキャッシュすることができます。
@defer
指定したフィールドを遅延的に取得する。
@export
指定したフィールドを変数として使うことができるようにする。
@nonreactive
指定したフィールドが変更されても再レンダリングが発生しないようにする。
ローカルステート
リアクティブ
makeVar
関数をread
関数かuseReactiveVar
フックを使ってリアクティブな処理にします。
値を取得するにはmakeVar
関数の戻り値の関数を実行する。
@client
@client
ディレクティブをクエリのフィールドに付与するとローカルにのみ有効なフィールドになる。
@clinet
ディレクティブが付与されたフィールドの値を生成はtypePolicies
のread
関数で行う。
@client @export(as: "authorId")
のようにローカルステートのフィールドをクエリで使うことができます。
クライアント用のクエリを定義する
typeDefsにextend type
したクエリを指定する。
テスト
https://www.apollographql.com/docs/react/development-testing/testing
パフォーマンス
バンドルサイズを小さくする方法 https://www.apollographql.com/docs/react/development-testing/reducing-bundle-size