Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save kenmori/ae2907e70740309954d9a63f2f2b18b3 to your computer and use it in GitHub Desktop.
Save kenmori/ae2907e70740309954d9a63f2f2b18b3 to your computer and use it in GitHub Desktop.
apollo-clientがQeuryやMutationした際のlocal cacheの作られ方を理解する

apollo-clientがQeuryやMutationした際のlocal cacheの作られ方を理解する

こちらはHow to update the Apollo Client’s cache after a mutationを意訳し、さらにapolloClientの仕様書での文章を読んでりかいしたことです。 英語読める方はリンク先、仕様書を見ることをお勧めします


Cacheアップデート

自動的にキャッシュをアップデートさせるためには queryすると 結果がlocalにキャッシュされる

queryの結果に対して何かのフィールドを更新、mutationすると結果がlocalにキャッシュされるが、 このときcacheされる条件は、

返り値に

  1. idを含んでいる

  2. titleを含んでいるから(アップデートしたフィールド)

ると

どこにでもある以前までのqueryの結果を参照している値は自動的に今回のmutation結果で更新される

そのために

mutationの返り値を得るためのフィールドとqueryの結果のそれを一致させておく必要がある

そのための、 ベストプラティクスは、 全ての結果を同期させるためにfragmentでフィールドをシェアすること。

キャッシュされないケース

author型の中のnameフィールドが結果として更新されない場合idが存在しないことが原因のケースがある

mutaton後に自動的にキャッシュが更新されないケース

  • 作成(create)
  • 削除(delete)
  • フィルター

mutationしたケース

この場合手動で更新する。 2つの方法がある

  • ブラウザをリフレッシュ
  • update関数でローカルキャッシュにアクセスして更新

3つめとして、refetchQueryがあるが、ネットワークを利用することになる

mutation後にrenderProps内で実行できるupdate関数の引数には

1つめに現在のcacheデータ、2つめにoptimisticレスポンスか実際のサーバーからのレスポンスが渡ってくる

optimasticレスポンスというのはオプションで設定できるもので、

サーバーからのmutationの返値をまたずに、事前にこちらが予測できうる返値を提供

キャッシュを更新することが可能です。

そのためユーザーは速く感じることができます

この場合update関数は2回呼ばれ、

2回目は実際のサーバーからの応答が返ってきます

refetchQueries vs update

refetchQueries・・・サーバーにqueryの再取得し正規化、キャッシュを新しいものにする

  • refetch={[string]}ならoperationネームを渡す

  • オブジェクトなら {query: “operationname”}

awaitRefetchQueries・・・デフォルトではmutationが終わる前にrefetchしないケースもある(defaultはfalse)

updateQueriesは・・・廃止される予定。updateを使うこと

update関数は当然local cacheを更新するのでrefetchQueriesより速く感じる

try-cactchをつかう

もしまだqueryfetchし終わっていないなら proxy.readQueryErrorを 投げ、アプリケーションはクラッシュします

queryが安全に扱えるようになった場合を保証するために try/chachを使いましょう

try/cactch、それ以外の方法はqueryがすでにcache内にあることを確認する方法があります

readQeurywriteQeryもエラーをなげます

書き込み操作時の間にキャッシュから読み込むとfieldがないためにエラーをなげることがあります

損失しているfieldは__typenameになるでしょう

variablesによるキャッシュの作られ方による違い

記事を扱うqueryがあるとして 全ての記事を叩くquery、 さらに公開未公開で叩いたqueryはそれぞれでキャッシュがつくられて

posts
posts({variables: {open: true}})
posts({variables: {open: false}})

3つたたくと ちがうエンティティのキャッシュ3つできる それぞれベてをreadQuery, writeQueryで更新する必要がある

また同じquery operation nameでリクエストした際でもvariablseの順番が違うと

{variables: {width: “100”, height:”50”}}
{variables: {height: “50”, width:”100"}}

別でキャッシュされる

posts({“width”: 100, “height”: 50})
posts({“height”: 50, “height”: 100})

順番はおなじでも値が違うvariablseを叩いても

{variables: {width: “100”, height:”50”}}
{variables: {height: “50”, width:”100”}}
{variables: {height: “50”, width:”600”}}

追加でつくられる

posts({“width”: 100, “height”: 50})
posts({“height”: 50, “height”: 100})
posts({“height”: 50, “height”: 600})

もし {variablse: pops.some} として 動的に値が渡ってきたものをリクエストしたら、

(props.someが {width: null, height: null}

としてprops.someが渡ってきたら)

cacheoperationname ({"width": null, "height": null}) になります

全く渡していなかったら

`gql`${SOME}`

posts({})

になる

see: How to update the Apollo Client’s cache after a mutation

author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment