🐥

useSWRのinitialData設定してる時に上手くfetchで更新かからない場合の対応

2022/04/25に公開

swrとnext.js組み合わせて使うときに事前フェッチでページの体験を上げることができるが、ドキュメント通りに作った場合initialDataに渡したデータが表示され続けてその後の更新が走ってなさそうだった

ドキュメント:https://swr.vercel.app/ja/docs/with-nextjs#事前レンダリング

↓のissueに同じような問題があげてある、useSWRをラップした関数を一個作ることで解決してそうなので真似して解決した

https://github.com/vercel/swr/issues/284

コード例

export const useSWR = <Data, Error>(
  key: keyInterface,
  fn?: fetcherFn<Data>,
  config?: ConfigInterface<Data, Error>
): responseInterface<Data, Error> => {
  const hasMounted = useRef(false)

  useEffect(() => {
    hasMounted.current = true
  }, [])

  return _useSWR<Data, Error>(key, fn, {
    ...config,
    initialData: hasMounted.current ? undefined : config?.initialData
  })
}

// ↓のように使う(普通のuseSWRと使い方同じ)
const useProductStatuses = (
  token: string,
  activeStatusCategory: string | null,
  activePeriod: string | null,
  pageIndex: number,
  pageCount: number,
  defaultProducts: FavoriteProduct[],
  totalCount: number,
  budgetSum: number
) => {
  const key = `/products/favorites?user_status=${activeStatusCategory ||
    'none'}&period=${activePeriod ||
    'none'}&page=${pageIndex}&count=${pageCount}`
  return useSWR<
    ApiResponse<{
      products: FavoriteProduct[]
      totalCount: number
      budgetSum: number
    }>,
    Error
  >([key, token], authFetcher, {
    initialData: {
      res: { products: defaultProducts, totalCount, budgetSum }
    }
  })
}

initialDataを初回以外ならundefinedにしてやるって対応がどっかしらで必要ぽい(↑だとuseRefとuseEffect使って実現してる)

Discussion