Open3

Apollo Clientのrefetchでハマった話

ApolloのuseQuery hookにはrefetchの機能があります
https://www.apollographql.com/docs/react/data/queries/#refetching

純粋な refetch() をすれば再度リクエストして最新のデータを取得します。
パラメータを追加指定してあげればその内容でリクエストしてくれます。

自分は以下のコードを書いてハマりました

期待値はこうです

  • 画面表示時点のはlimit10で最大10件のレコードを表示する
  • Clickすることで、limit100で再フェッチして最大100件のレコードを表示する

なにが起こったか分かりますか?

const Page: NextPage = () => {
  const id = 'hogeid'
  const currentTime = dayjs().format();
  const {data, loading, refetch} = useQuery(HogeDocument, {
    variables: {
      id,
      now: currentTime,
      limit: 10,
    },
  });
  return <div>
    <button onClick={()=>{refetch({ limit: 100, })} }>click</button>
  </div>
};
遭遇した事象

常に最大10件の表示になってしまう
実際にはClickを押して refetch のリクエスト(最大100件)が発生するが、その直後に元のリクエスト(最大10件)が発生してしまい、後者の結果が画面に表示される

予想通りだったでしょうか?
正解できなかった人は次を御覧ください

ネタバラシ

currentTimeが画面表示処理の度に更新され、その結果元のキャッシュを上書こうとする挙動になっていました
なので期待通りの挙動にするにはcurrentTimeをメモ化する必要がありました
このように評価の度に更新される値をリクエストのパラメータとして指定する場合は適切に扱う必要があるので注意です

const Page: NextPage = () => {
  const id = 'hogeid'
  const currentTime = useMemo(() => {
    return dayjs().format();
  }, []);
  const {data, loading, refetch} = useQuery(HogeDocument, {
    variables: {
      id,
      now: currentTime,
      limit: 10,
    },
  });
  return <div>
    <button onClick={()=>{refetch({ limit: 100, })} }>click</button>
  </div>
};
ログインするとコメントできます