# GraphQL - Appolo

# Mutation 時のキャッシュの更新方法

# refetchQueries を使う方法

  • Mutation が成功した後に別のクエリを投げてキャッシュを更新する
  • メリット --- 簡単かつシンプル
  • デメリット --- リクエスト量が増える
createAccount({
  variables: { account: data },
  refetchQueries: ['GetAccounts'], // クエリ名を記載する
});

# custom merge function

アイテムを削除したのちに refetchQueries で全件取得をすると、下記のようなメッセージが出る場合がある。

Cache data may be lost when replacing the accounts field of a Query object.

この場合は、下記のように custom merge function を明示的に設定してやるとよい。

const client = new ApolloClient({
  cache: new InMemoryCache({
    typePolicies: {
      Query: {
        fields: {
          accounts: {
            // custom merge function
            // - accountsを取得したときはキャッシュのデータをまるごと置き換える
            // - ページネーションなどを行うときはより細かい制御が必要となる
            merge: (_existingAccount, incomingAccounts) => incomingAccounts,
          },
        },
      },
    },
  }),
});

# update を使う方法

  • cache.modify()などを使用し、キャッシュを完全にコントロールできる
  • メリット --- リクエスト量は最少ですむ
  • デメリット --- 処理の記述が煩雑
// 作成の例
createAccount({
  variables: { account: data },
  update: (cache, fetchResult) => {
    const newAccountRef = cache.writeFragment({
      data: fetchResult.data?.createAccount?.account,
      fragment: gql`
        fragment NewAccountType on AccountType {
          id
          name
        }
      `,
    });
    cache.modify({
      fields: {
        accounts: (existingAccounts) => [...existingAccounts, newAccountRef],
      },
    });
  },
});

// 削除の例
deleteAccount({
  variables: { id },
  update: (cache, fetchResult) => {
    cache.modify({
      fields: {
        accounts: (existingAccounts: AccountType[], { readField }) =>
          existingAccounts.filter(
            (existingAccount) =>
              readField('id', existingAccount) !==
              fetchResult.data?.deleteAccount?.id,
          ),
      },
    });
  },
});