見出し画像

ReactQueryを使ってキャッシュデータに明示的にアクセスするやり方について

こんにちわ。nap5です。

ReactQueryを使ってキャッシュデータに明示的にアクセスするやり方について紹介したいと思います。


結論からだとgetQueryCacheを使ってキャッシュクライアントをつくり、



そのあとはこのドキュメントに従って


以下のようなフックを作り、目的の機能を達成します。


import { queryClient } from '@/libs/queryClient'
import { Cursor, FaunaBackendCollectionHistoryResponse } from '@/types/response'

type LoadMoreShortHand = {
  data: FaunaBackendCollectionHistoryResponse[]
  after: Cursor
}

const useQueryCache = (): LoadMoreShortHand[] | undefined => {
  const queryCacheClient = queryClient.getQueryCache()
  const queries = queryCacheClient.findAll()
  if (queries.length === 0) {
    return
  }
  const cachedData: LoadMoreShortHand[] = []
  queries.forEach(({ queryKey }) => {
    const data = queryClient.getQueryData(queryKey)
    if (data) {
      cachedData.push(data as LoadMoreShortHand)
    }
  })
  return cachedData
}

export default useQueryCache


ただ、このままだとコンポーネント間ですべてのクエリ結果をグルーピングせずにまとめてしまうので、引数にメインのクエリキーを受け取ってコンポーネントごとにクエリ結果をキャッシュできるフックにしておきます。そちらの方がハンディです。

import { queryClient } from '@/libs/queryClient'
import { Cursor, FaunaBackendCollectionHistoryResponse } from '@/types/response'

type LoadMoreShortHand = {
  data: FaunaBackendCollectionHistoryResponse[]
  after: Cursor
}

const useQueryCache = (mainQueryKey: string): LoadMoreShortHand[] | undefined => {
  const queryCacheClient = queryClient.getQueryCache()
  const queries = queryCacheClient.findAll()
  if (queries.length === 0) {
    return
  }
  const cachedData: LoadMoreShortHand[] = []
  queries.forEach(({ queryKey }) => {
    const data = queryClient.getQueryData(queryKey, {
      predicate(query) {
        return query.queryKey.includes(mainQueryKey)
      },
    })
    if (data) {
      cachedData.push(data as LoadMoreShortHand)
    }
  })
  return cachedData
}

export default useQueryCache


FaunaDBだとPaginate関数があるので、いわゆる「もっと読む」「Load More」などの機能を実現しやすくなります。


Paginate関数のデフォルトの使い勝手だと古いデータから遡って「Load More」を少しずつ(たとえば、10件ずつ程度)実行することでヒストリカルな時系列UIを実現しやすくなります。「Load More」ボタンが上にくるイメージです。


よく見られるのは新しいデータから遡って古いデータまでたどり着くものだと思います。「Load More」ボタンが下にくるイメージです。


「Load More」ボタンが上にあるヒストリカルな時系列UI




この挙動は以下のライブラリとも相性がいいと思います。



この類はカーソルベースのページネーションとオフセットベースのページネーションの話にも絡んできます。


ページネーション関連で参考にしたリンクは以下にまとめます。





カーソルベースのページネーションでPrevとNextを使った実装(用途としては適切ではあまりないと思いますが)はキャッシュの利かせ方が、裏のバックエンドでの制約に依存する側面が出たりすることが分かったので、気を付けたいです。たとえば、FaunaDBなどのPaginate関数の引数の取り方など。キャッシュを気にしなければ、実装しちゃってもいいかなという感じです。


PrevとNextを使ったページネーションするなら、ページ番号を管理してそれようのバックエンドの仕組みが必要です。


簡単ですが、以上です。

この記事が気に入ったらサポートをしてみませんか?