Open4

GraphQL クライアントの比較

seyaseya

ほしいもの

  • useFetch 系の関数
    • const { data, error, loading } = useHogeQuery()
  • 上記関数がスキーマから graphql-codegen で生成できる
  • キャッシュがいい感じにできる
    • ここが違いが最も現れる部分そうなので、具体化して検討する
  • SSG, SSR で動く
seyaseya

キャッシュについて

正規化されたキャッシュが必要なのか

この記事を読んで本当に正規化されたキャッシュが必要なのかを考えてみた方がいいなと思った
https://blog.logrocket.com/why-i-finally-switched-to-urql-from-apollo-client/

正規化の目的

キャッシュされたデータを使いつつ最新の状態を保つため
例えば「記事の一覧」をあるページで取得して、他のページでその記事にいいね!を実行した場合、一覧を取得したページに戻ったときに一覧のデータを再取得せずとも「いいね!をした」という状態はアップデートされていて欲しい、といった感じ。

正規化するために何が必要なのか

Apollo では id + __typename で unique な ID が作られ正規化されている

Splitting the results into individual objects
Assigning a logically unique identifier to each object so that the cache can keep track of the entity in a stable way
Storing the objects in a flattened data structure (normalized items)

https://www.apollographql.com/blog/apollo-client/caching/demystifying-cache-normalization/

mutation を起こした時に結果をの値を返すようにする

手動で update 関数を書く

function AddTodo() {
  let input;
  const [addTodo] = useMutation(ADD_TODO, {
    update(cache, { data: { addTodo } }) {
      cache.modify({
        fields: {
          todos(existingTodos = []) {
            const newTodoRef = cache.writeFragment({
              data: addTodo,
              fragment: gql`
                fragment NewTodo on Todo {
                  id
                  type
                }
              `
            });
            return [...existingTodos, newTodoRef];
          }
        }
      });
    }
  });

正規化しない場合はどうするか

一つ解決策としてあるのが毎回再取得するということ。
これでパフォーマンスの問題が大して大きくならなければこれでいい気がする。

Apollo なら refetchQueries を指定する。

Urql なら設定なしでやってくれるっぽい。
https://zenn.dev/adwd/articles/f4c5c5120467bb