loadMoreInfinite.ts 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import { useSWRConfig } from "swr";
  2. import useSWRInfinite from "swr/infinite";
  3. export type TResponseData<D> = {
  4. data: D
  5. nextId?: string
  6. totalCount?: null | number
  7. pageIndex?: number
  8. pageSize?: number
  9. }
  10. export const createKey = (query: string, pageSize: number = 10, extra: Record<string, any> = []) => {
  11. return (pageIndex: number, previousPageData) => {
  12. // pageIndex 后端要求是从 1 开始
  13. if (pageIndex === 0)
  14. return [
  15. query,
  16. { nextId: undefined, pageSize, pageIndex: pageIndex + 1 },
  17. extra,
  18. ];
  19. // 如果是以 pageIndex 作为分页依据, 即有pageIndex 且 没有 nextId
  20. //
  21. if (previousPageData && previousPageData.pageIndex && !previousPageData.nextId) {
  22. return [
  23. query,
  24. { pageSize, pageIndex: previousPageData.pageIndex + 1 },
  25. extra,
  26. ];
  27. }
  28. if (previousPageData && previousPageData.nextId) {
  29. return [
  30. query,
  31. { pageSize, nextId: previousPageData.nextId},
  32. extra,
  33. ];
  34. }
  35. return null;
  36. };
  37. }
  38. export const useLoadMoreInfinite = <T>(getKey, fetcher, params = {}) => {
  39. const {cache} = useSWRConfig()
  40. const { data, setSize, size, mutate, isLoading, error } = useSWRInfinite<{
  41. data: T
  42. nextId?: string
  43. totalCount?: null | number
  44. pageIndex?: number
  45. pageSize?: number
  46. }>(getKey, fetcher, {
  47. ...params,
  48. revalidateIfStale: false,
  49. revalidateFirstPage: false,
  50. onErrorRetry(err, key, config, revalidate, revalidateOpts) {
  51. if (err.code === 404) return
  52. if (err.code === 401) {
  53. // 获取所有缓存的 key(SWR 缓存基于 key 存储)
  54. const allKeys = Array.from(cache.keys());
  55. // 过滤出当前分页请求相关的 key(如包含 /api/list?page=)
  56. const relevantKeys = allKeys.filter(_key => _key.includes(key));
  57. // 逐个删除这些 key 的缓存
  58. relevantKeys.forEach(key => cache.delete(key));
  59. return
  60. }
  61. if (revalidateOpts.retryCount >= 3) return
  62. },
  63. });
  64. // 扁平化后的数据列表
  65. const list = (data?.flatMap((page) => page?.data || []) || []) as T;
  66. // 原分页数据二维数组
  67. const pages = data
  68. const pageIndex = size
  69. const loadMore = () => {
  70. setSize((size) => size + 1);
  71. }
  72. return {
  73. data,
  74. list,
  75. pageIndex,
  76. isLoading,
  77. pages,
  78. mutate,
  79. setSize,
  80. loadMore,
  81. error,
  82. }
  83. }