2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

apollo clientのcache機能を使った際にcacheが上書きされる

Posted at

はじめに

apollo client V3.0のベータ版がリリースされ、そろそろcacheを使いこなしたいと思う今日この頃。凡ミスで時間を取られたので、備忘録として残しておきます。

今回出会った問題

今回はコメントリストを呼び出す例を題材に出会った問題を書き残しておきます。

Server側の実装

まずは以下のようなサーバー側のコードを考えます。

sever.js
const { ApolloServer, gql } = require("apollo-server");

const typeDefs = gql`
  type Comment {
    id: ID
    title: String
    comment: String
  }

  type Query {
    commentDetail(title: String): Comment
  }
`;

const commentsList = [
  {
    id: 1,
    title: "初めて利用してみた",
    comment: "このサービスは素晴らしい"
  },
  {
    id: 1,
    title: "何回でも使いたくなるサービス",
    comment: "こんな素晴らしいサービスは見たことが無い"
  }
];

const resolvers = {
  Query: {
    commentDetail: (root, args) => {
      const com = commentsList.find(p => p.title === args.title);
      return com;
    }
  }
};

const server = new ApolloServer({ typeDefs, resolvers });

server.listen().then(({ url }) => {
  console.log(`Server ready at ${url}`);
});

commentListのidが重複してるのに気づくと思います。
この状態でcacheを有効化してみたいと思います。

cacheの設定

InMemoryCacheを使います

import { ApolloClient, HttpLink, InMemoryCache } from "@apollo/client";

const link = new HttpLink({
  uri: "http://localhost:4000/graphql"
});

const client = new ApolloClient({
  link,
  cache: new InMemoryCache(),
  defaultOptions: {
    watchQuery: {
      fetchPolicy: "cache-first"
    }
  }
});

上のようにApolloClientを呼び出す際、fetchPolicy"cache-first"を指定してあります。ただデフォルトで"cache-first"が指定されているので、書いても書かなくても同じです。

query

今回以下の2つのqueryを交互に投げてcacheはどう保存されていくか、確認します

const COMMENTS_QUERY = gql`
  {
    commentDetail(title:"初めて利用してみた"){
      id
      comment
    }
  }
`;

const COMMENTS_QUERY = gql`
  {
    commentDetail(title:"何回でも使いたくなるサービス"){
      id
      comment
    }
  }
`;

結果

InMemorycachedata内部にROOT_QUERYがあり、そこに呼び出されたデータが蓄積されていきます。そしてidが付いているものは、__refに参照先が追加され、ROOT_QUERYと同階層に参照元データが追加されて行きます。今回idを同じに設定したため __refが同じcacheを見に行き、表示が更新されないということになっています。(下にcacheの中身の参考画像を貼ります。)
これはidをちゃんとユニークにつけておけば問題ないです。

スクリーンショット 2020-02-10 18.01.31.png

idをつけなかったらどうなるか

今idが同じものであったためにcacheの重複が起こりました。idを消すと__refが消え、ROOT_QUERYにデータが全て保存されるようになります。今回の場合、commentDetail({"title":"何回でも使いたくなるサービス"})の部分がkeyになり、cacheにどんどん保存されます。この場合だと参照先がないので、同じデータを見にいくことはありません。しかしこの場合もtitleが同じ場合は希望通りの挙動が出ない場合があるので、idはちゃんと降っておいたほうがいいかなと思います。

参考文献

以下の記事を参考にさせていただきました。ありがとうございました。
apollo-clientを使っていてデータが変に重複してる(キャッシュが変)?と思った時に見てみる事

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?