Initial commit
This commit is contained in:
commit
89053153cc
8152 files changed
+2086461
No files matched your search
+48
@@ -0,0 +1,48 @@
|
||||
import { A as Arguments, B as BareFetcher, e as SWRConfiguration, f as StrictTupleKey, c as SWRResponse, d as MutatorCallback, g as MutatorOptions, M as Middleware } from '../types-l2s7dphv.js';
|
||||
|
||||
type FetcherResponse<Data = unknown> = Data | Promise<Data>;
|
||||
type SWRInfiniteFetcher<Data = any, KeyLoader extends SWRInfiniteKeyLoader = SWRInfiniteKeyLoader> = KeyLoader extends (...args: any[]) => any ? ReturnType<KeyLoader> extends (infer T) | null | false | undefined ? (args: T) => FetcherResponse<Data> : never : never;
|
||||
type SWRInfiniteKeyLoader<Data = any, Args extends Arguments = Arguments> = (index: number, previousPageData: Data | null) => Args;
|
||||
interface SWRInfiniteCompareFn<Data = any> {
|
||||
(a: Data | undefined, b: Data | undefined): boolean;
|
||||
(a: Data[] | undefined, b: Data[] | undefined): boolean;
|
||||
}
|
||||
interface SWRInfiniteConfiguration<Data = any, Error = any, Fn extends SWRInfiniteFetcher<Data> = BareFetcher<Data>> extends Omit<SWRConfiguration<Data[], Error>, 'compare'> {
|
||||
initialSize?: number;
|
||||
revalidateAll?: boolean;
|
||||
persistSize?: boolean;
|
||||
revalidateFirstPage?: boolean;
|
||||
parallel?: boolean;
|
||||
fetcher?: Fn;
|
||||
compare?: SWRInfiniteCompareFn<Data>;
|
||||
}
|
||||
interface SWRInfiniteRevalidateFn<Data = any> {
|
||||
(data: Data, key: Arguments): boolean;
|
||||
}
|
||||
type SWRInfiniteKeyedMutator<Data> = <MutationData = Data>(data?: Data | Promise<Data | undefined> | MutatorCallback<Data>, opts?: boolean | SWRInfiniteMutatorOptions<Data, MutationData>) => Promise<Data | MutationData | undefined>;
|
||||
interface SWRInfiniteMutatorOptions<Data = any, MutationData = Data> extends Omit<MutatorOptions<Data, MutationData>, 'revalidate'> {
|
||||
revalidate?: boolean | SWRInfiniteRevalidateFn<Data extends unknown[] ? Data[number] : never>;
|
||||
}
|
||||
interface SWRInfiniteResponse<Data = any, Error = any> extends Omit<SWRResponse<Data[], Error>, 'mutate'> {
|
||||
size: number;
|
||||
setSize: (size: number | ((_size: number) => number)) => Promise<Data[] | undefined>;
|
||||
mutate: SWRInfiniteKeyedMutator<Data[]>;
|
||||
}
|
||||
interface SWRInfiniteHook {
|
||||
<Data = any, Error = any, KeyLoader extends SWRInfiniteKeyLoader = (index: number, previousPageData: Data | null) => StrictTupleKey>(getKey: KeyLoader): SWRInfiniteResponse<Data, Error>;
|
||||
<Data = any, Error = any, KeyLoader extends SWRInfiniteKeyLoader = (index: number, previousPageData: Data | null) => StrictTupleKey>(getKey: KeyLoader, fetcher: SWRInfiniteFetcher<Data, KeyLoader> | null): SWRInfiniteResponse<Data, Error>;
|
||||
<Data = any, Error = any, KeyLoader extends SWRInfiniteKeyLoader = (index: number, previousPageData: Data | null) => StrictTupleKey>(getKey: KeyLoader, config: SWRInfiniteConfiguration<Data, Error, SWRInfiniteFetcher<Data, KeyLoader>> | undefined): SWRInfiniteResponse<Data, Error>;
|
||||
<Data = any, Error = any, KeyLoader extends SWRInfiniteKeyLoader = (index: number, previousPageData: Data | null) => StrictTupleKey>(getKey: KeyLoader, fetcher: SWRInfiniteFetcher<Data, KeyLoader> | null, config: SWRInfiniteConfiguration<Data, Error, SWRInfiniteFetcher<Data, KeyLoader>> | undefined): SWRInfiniteResponse<Data, Error>;
|
||||
<Data = any, Error = any>(getKey: SWRInfiniteKeyLoader): SWRInfiniteResponse<Data, Error>;
|
||||
<Data = any, Error = any>(getKey: SWRInfiniteKeyLoader, fetcher: BareFetcher<Data> | null): SWRInfiniteResponse<Data, Error>;
|
||||
<Data = any, Error = any>(getKey: SWRInfiniteKeyLoader, config: SWRInfiniteConfiguration<Data, Error, BareFetcher<Data>> | undefined): SWRInfiniteResponse<Data, Error>;
|
||||
<Data = any, Error = any>(getKey: SWRInfiniteKeyLoader, fetcher: BareFetcher<Data> | null, config: SWRInfiniteConfiguration<Data, Error, BareFetcher<Data>> | undefined): SWRInfiniteResponse<Data, Error>;
|
||||
}
|
||||
|
||||
declare const unstable_serialize: (getKey: SWRInfiniteKeyLoader) => string;
|
||||
|
||||
declare const infinite: Middleware;
|
||||
declare const useSWRInfinite: SWRInfiniteHook;
|
||||
|
||||
export { useSWRInfinite as default, infinite, unstable_serialize };
|
||||
export type { SWRInfiniteCompareFn, SWRInfiniteConfiguration, SWRInfiniteFetcher, SWRInfiniteHook, SWRInfiniteKeyLoader, SWRInfiniteKeyedMutator, SWRInfiniteMutatorOptions, SWRInfiniteResponse };
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
import { A as Arguments, B as BareFetcher, g as SWRConfiguration, z as StrictTupleKey, x as SWRResponse, M as MutatorCallback, e as MutatorOptions, i as Middleware } from '../types-m1fld6v2.js';
|
||||
|
||||
type FetcherResponse<Data = unknown> = Data | Promise<Data>;
|
||||
type SWRInfiniteFetcher<Data = any, KeyLoader extends SWRInfiniteKeyLoader = SWRInfiniteKeyLoader> = KeyLoader extends (...args: any[]) => any ? ReturnType<KeyLoader> extends (infer T) | null | false | undefined ? (args: T) => FetcherResponse<Data> : never : never;
|
||||
type SWRInfiniteKeyLoader<Data = any, Args extends Arguments = Arguments> = (index: number, previousPageData: Data | null) => Args;
|
||||
interface SWRInfiniteCompareFn<Data = any> {
|
||||
(a: Data | undefined, b: Data | undefined): boolean;
|
||||
(a: Data[] | undefined, b: Data[] | undefined): boolean;
|
||||
}
|
||||
interface SWRInfiniteConfiguration<Data = any, Error = any, Fn extends SWRInfiniteFetcher<Data> = BareFetcher<Data>> extends Omit<SWRConfiguration<Data[], Error>, 'compare'> {
|
||||
initialSize?: number;
|
||||
revalidateAll?: boolean;
|
||||
persistSize?: boolean;
|
||||
revalidateFirstPage?: boolean;
|
||||
parallel?: boolean;
|
||||
fetcher?: Fn;
|
||||
compare?: SWRInfiniteCompareFn<Data>;
|
||||
}
|
||||
interface SWRInfiniteRevalidateFn<Data = any> {
|
||||
(data: Data, key: Arguments): boolean;
|
||||
}
|
||||
type SWRInfiniteKeyedMutator<Data> = <MutationData = Data>(data?: Data | Promise<Data | undefined> | MutatorCallback<Data>, opts?: boolean | SWRInfiniteMutatorOptions<Data, MutationData>) => Promise<Data | MutationData | undefined>;
|
||||
interface SWRInfiniteMutatorOptions<Data = any, MutationData = Data> extends Omit<MutatorOptions<Data, MutationData>, 'revalidate'> {
|
||||
revalidate?: boolean | SWRInfiniteRevalidateFn<Data extends unknown[] ? Data[number] : never>;
|
||||
}
|
||||
interface SWRInfiniteResponse<Data = any, Error = any> extends Omit<SWRResponse<Data[], Error>, 'mutate'> {
|
||||
size: number;
|
||||
setSize: (size: number | ((_size: number) => number)) => Promise<Data[] | undefined>;
|
||||
mutate: SWRInfiniteKeyedMutator<Data[]>;
|
||||
}
|
||||
interface SWRInfiniteHook {
|
||||
<Data = any, Error = any, KeyLoader extends SWRInfiniteKeyLoader = (index: number, previousPageData: Data | null) => StrictTupleKey>(getKey: KeyLoader): SWRInfiniteResponse<Data, Error>;
|
||||
<Data = any, Error = any, KeyLoader extends SWRInfiniteKeyLoader = (index: number, previousPageData: Data | null) => StrictTupleKey>(getKey: KeyLoader, fetcher: SWRInfiniteFetcher<Data, KeyLoader> | null): SWRInfiniteResponse<Data, Error>;
|
||||
<Data = any, Error = any, KeyLoader extends SWRInfiniteKeyLoader = (index: number, previousPageData: Data | null) => StrictTupleKey>(getKey: KeyLoader, config: SWRInfiniteConfiguration<Data, Error, SWRInfiniteFetcher<Data, KeyLoader>> | undefined): SWRInfiniteResponse<Data, Error>;
|
||||
<Data = any, Error = any, KeyLoader extends SWRInfiniteKeyLoader = (index: number, previousPageData: Data | null) => StrictTupleKey>(getKey: KeyLoader, fetcher: SWRInfiniteFetcher<Data, KeyLoader> | null, config: SWRInfiniteConfiguration<Data, Error, SWRInfiniteFetcher<Data, KeyLoader>> | undefined): SWRInfiniteResponse<Data, Error>;
|
||||
<Data = any, Error = any>(getKey: SWRInfiniteKeyLoader): SWRInfiniteResponse<Data, Error>;
|
||||
<Data = any, Error = any>(getKey: SWRInfiniteKeyLoader, fetcher: BareFetcher<Data> | null): SWRInfiniteResponse<Data, Error>;
|
||||
<Data = any, Error = any>(getKey: SWRInfiniteKeyLoader, config: SWRInfiniteConfiguration<Data, Error, BareFetcher<Data>> | undefined): SWRInfiniteResponse<Data, Error>;
|
||||
<Data = any, Error = any>(getKey: SWRInfiniteKeyLoader, fetcher: BareFetcher<Data> | null, config: SWRInfiniteConfiguration<Data, Error, BareFetcher<Data>> | undefined): SWRInfiniteResponse<Data, Error>;
|
||||
}
|
||||
|
||||
declare const unstable_serialize: (getKey: SWRInfiniteKeyLoader) => string;
|
||||
|
||||
declare const infinite: Middleware;
|
||||
declare const useSWRInfinite: SWRInfiniteHook;
|
||||
|
||||
export { useSWRInfinite as default, infinite, unstable_serialize };
|
||||
export type { SWRInfiniteCompareFn, SWRInfiniteConfiguration, SWRInfiniteFetcher, SWRInfiniteHook, SWRInfiniteKeyLoader, SWRInfiniteKeyedMutator, SWRInfiniteMutatorOptions, SWRInfiniteResponse };
|
||||
+270
@@ -0,0 +1,270 @@
|
||||
Object.defineProperty(exports, '__esModule', { value: true });
|
||||
|
||||
var React = require('react');
|
||||
var useSwr = require('../use-swr-guqrv3k1.js');
|
||||
var bunchee_group_0 = require('../config-context-s960zqob.js');
|
||||
var _internal_index = require('../_internal/index.js');
|
||||
var shim = require('use-sync-external-store/shim');
|
||||
var _internal_constants = require('../_internal/constants.js');
|
||||
|
||||
const getFirstPageKey = (getKey)=>{
|
||||
return bunchee_group_0.serialize(getKey ? getKey(0, null) : null)[0];
|
||||
};
|
||||
const unstable_serialize = (getKey)=>{
|
||||
return _internal_constants.INFINITE_PREFIX + getFirstPageKey(getKey);
|
||||
};
|
||||
|
||||
// We have to several type castings here because `useSWRInfinite` is a special
|
||||
// hook where `key` and return type are not like the normal `useSWR` types.
|
||||
const EMPTY_PROMISE = Promise.resolve();
|
||||
const infinite = (useSWRNext)=>(getKey, fn, config)=>{
|
||||
const didMountRef = React.useRef(false);
|
||||
const { cache, initialSize = 1, revalidateAll = false, persistSize = false, revalidateFirstPage = true, revalidateOnMount = false, parallel = false } = config;
|
||||
const [, , , PRELOAD] = bunchee_group_0.SWRGlobalState.get(bunchee_group_0.cache);
|
||||
// The serialized key of the first page. This key will be used to store
|
||||
// metadata of this SWR infinite hook.
|
||||
let infiniteKey;
|
||||
try {
|
||||
infiniteKey = getFirstPageKey(getKey);
|
||||
if (infiniteKey) infiniteKey = _internal_constants.INFINITE_PREFIX + infiniteKey;
|
||||
} catch (err) {
|
||||
// Not ready yet.
|
||||
}
|
||||
const [get, set, subscribeCache] = bunchee_group_0.createCacheHelper(cache, infiniteKey);
|
||||
const getSnapshot = React.useCallback(()=>{
|
||||
const size = bunchee_group_0.isUndefined(get()._l) ? initialSize : get()._l;
|
||||
return size;
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
cache,
|
||||
infiniteKey,
|
||||
initialSize
|
||||
]);
|
||||
shim.useSyncExternalStore(React.useCallback((callback)=>{
|
||||
if (infiniteKey) return subscribeCache(infiniteKey, ()=>{
|
||||
callback();
|
||||
});
|
||||
return ()=>{};
|
||||
}, // eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[
|
||||
cache,
|
||||
infiniteKey
|
||||
]), getSnapshot, getSnapshot);
|
||||
const resolvePageSize = React.useCallback(()=>{
|
||||
const cachedPageSize = get()._l;
|
||||
return bunchee_group_0.isUndefined(cachedPageSize) ? initialSize : cachedPageSize;
|
||||
// `cache` isn't allowed to change during the lifecycle
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
infiniteKey,
|
||||
initialSize
|
||||
]);
|
||||
// keep the last page size to restore it with the persistSize option
|
||||
const lastPageSizeRef = React.useRef(resolvePageSize());
|
||||
// When the page key changes, we reset the page size if it's not persisted
|
||||
bunchee_group_0.useIsomorphicLayoutEffect(()=>{
|
||||
if (!didMountRef.current) {
|
||||
didMountRef.current = true;
|
||||
return;
|
||||
}
|
||||
if (infiniteKey) {
|
||||
// If the key has been changed, we keep the current page size if persistSize is enabled
|
||||
// Otherwise, we reset the page size to cached pageSize
|
||||
set({
|
||||
_l: persistSize ? lastPageSizeRef.current : resolvePageSize()
|
||||
});
|
||||
}
|
||||
// `initialSize` isn't allowed to change during the lifecycle
|
||||
}, [
|
||||
infiniteKey,
|
||||
cache
|
||||
]);
|
||||
// Needs to check didMountRef during mounting, not in the fetcher
|
||||
const shouldRevalidateOnMount = revalidateOnMount && !didMountRef.current;
|
||||
// Actual SWR hook to load all pages in one fetcher.
|
||||
const swr = useSWRNext(infiniteKey, async (key)=>{
|
||||
// get the revalidate context
|
||||
const forceRevalidateAll = get()._i;
|
||||
const shouldRevalidatePage = get()._r;
|
||||
// Capture the cache's unload generation (bumped by every `unload()`
|
||||
// call) so page responses that resolve after an unload are not
|
||||
// written back to the cleared cache.
|
||||
const state = bunchee_group_0.SWRGlobalState.get(cache);
|
||||
const unloadGeneration = state[8];
|
||||
const unloadedDuringRequest = ()=>state[8] !== unloadGeneration;
|
||||
set({
|
||||
_r: bunchee_group_0.UNDEFINED
|
||||
});
|
||||
// return an array of page data
|
||||
const data = [];
|
||||
const pageSize = resolvePageSize();
|
||||
const [getCache] = bunchee_group_0.createCacheHelper(cache, key);
|
||||
const cacheData = getCache().data;
|
||||
const revalidators = [];
|
||||
let previousPageData = null;
|
||||
for(let i = 0; i < pageSize; ++i){
|
||||
const [pageKey, pageArg] = bunchee_group_0.serialize(getKey(i, parallel ? null : previousPageData));
|
||||
if (!pageKey) {
|
||||
break;
|
||||
}
|
||||
const [getSWRCache, setSWRCache] = bunchee_group_0.createCacheHelper(cache, pageKey);
|
||||
// Get the cached page data.
|
||||
let pageData = getSWRCache().data;
|
||||
// should fetch (or revalidate) if:
|
||||
// - `revalidateAll` is enabled
|
||||
// - `mutate()` called
|
||||
// - the cache is missing
|
||||
// - it's the first page and it's not the initial render
|
||||
// - `revalidateOnMount` is enabled and it's on mount
|
||||
// - cache for that page has changed
|
||||
const shouldFetchPage = revalidateAll || forceRevalidateAll || bunchee_group_0.isUndefined(pageData) || revalidateFirstPage && !i && !bunchee_group_0.isUndefined(cacheData) || shouldRevalidateOnMount || cacheData && !bunchee_group_0.isUndefined(cacheData[i]) && !config.compare(cacheData[i], pageData);
|
||||
if (fn && (typeof shouldRevalidatePage === 'function' ? shouldRevalidatePage(pageData, pageArg) : shouldFetchPage)) {
|
||||
const revalidate = async ()=>{
|
||||
const hasPreloadedRequest = pageKey in PRELOAD;
|
||||
if (!hasPreloadedRequest) {
|
||||
pageData = await fn(pageArg);
|
||||
} else {
|
||||
const req = PRELOAD[pageKey];
|
||||
// delete the preload cache key before resolving it
|
||||
// in case there's an error
|
||||
delete PRELOAD[pageKey];
|
||||
// get the page data from the preload cache
|
||||
pageData = await req;
|
||||
}
|
||||
if (!unloadedDuringRequest()) {
|
||||
setSWRCache({
|
||||
data: pageData,
|
||||
_k: pageArg
|
||||
});
|
||||
}
|
||||
data[i] = pageData;
|
||||
};
|
||||
if (parallel) {
|
||||
revalidators.push(revalidate);
|
||||
} else {
|
||||
await revalidate();
|
||||
}
|
||||
} else {
|
||||
data[i] = pageData;
|
||||
}
|
||||
if (!parallel) {
|
||||
previousPageData = pageData;
|
||||
}
|
||||
}
|
||||
// flush all revalidateions in parallel
|
||||
if (parallel) {
|
||||
await Promise.all(revalidators.map((r)=>r()));
|
||||
}
|
||||
// once we executed the data fetching based on the context, clear the
|
||||
// context. Skipped after an unload so the cleared meta entry isn't
|
||||
// re-created.
|
||||
if (!unloadedDuringRequest()) {
|
||||
set({
|
||||
_i: bunchee_group_0.UNDEFINED
|
||||
});
|
||||
}
|
||||
// return the data
|
||||
return data;
|
||||
}, config);
|
||||
const mutate = React.useCallback(// eslint-disable-next-line func-names
|
||||
function(data, opts) {
|
||||
// When passing as a boolean, it's explicitly used to disable/enable
|
||||
// revalidation.
|
||||
const options = typeof opts === 'boolean' ? {
|
||||
revalidate: opts
|
||||
} : opts || {};
|
||||
// Default to true.
|
||||
const shouldRevalidate = options.revalidate !== false;
|
||||
// It is possible that the key is still falsy.
|
||||
if (!infiniteKey) return EMPTY_PROMISE;
|
||||
if (shouldRevalidate) {
|
||||
if (!bunchee_group_0.isUndefined(data)) {
|
||||
// We only revalidate the pages that are changed
|
||||
set({
|
||||
_i: false,
|
||||
_r: options.revalidate
|
||||
});
|
||||
} else {
|
||||
// Calling `mutate()`, we revalidate all pages
|
||||
set({
|
||||
_i: true,
|
||||
_r: options.revalidate
|
||||
});
|
||||
}
|
||||
}
|
||||
return arguments.length ? swr.mutate(data, {
|
||||
...options,
|
||||
revalidate: shouldRevalidate
|
||||
}) : swr.mutate();
|
||||
}, // swr.mutate is always the same reference
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[
|
||||
infiniteKey,
|
||||
cache
|
||||
]);
|
||||
// Extend the SWR API
|
||||
const setSize = React.useCallback((arg)=>{
|
||||
// It is possible that the key is still falsy.
|
||||
if (!infiniteKey) return EMPTY_PROMISE;
|
||||
const [, changeSize] = bunchee_group_0.createCacheHelper(cache, infiniteKey);
|
||||
let size;
|
||||
if (bunchee_group_0.isFunction(arg)) {
|
||||
size = arg(resolvePageSize());
|
||||
} else if (typeof arg == 'number') {
|
||||
size = arg;
|
||||
}
|
||||
if (typeof size != 'number') return EMPTY_PROMISE;
|
||||
changeSize({
|
||||
_l: size
|
||||
});
|
||||
lastPageSizeRef.current = size;
|
||||
// Calculate the page data after the size change.
|
||||
const data = [];
|
||||
const [getInfiniteCache] = bunchee_group_0.createCacheHelper(cache, infiniteKey);
|
||||
let previousPageData = null;
|
||||
for(let i = 0; i < size; ++i){
|
||||
const [pageKey] = bunchee_group_0.serialize(getKey(i, previousPageData));
|
||||
const [getCache] = bunchee_group_0.createCacheHelper(cache, pageKey);
|
||||
// Get the cached page data.
|
||||
const pageData = pageKey ? getCache().data : bunchee_group_0.UNDEFINED;
|
||||
// Call `mutate` with infinte cache data if we can't get it from the page cache.
|
||||
if (bunchee_group_0.isUndefined(pageData)) {
|
||||
return mutate(getInfiniteCache().data);
|
||||
}
|
||||
data.push(pageData);
|
||||
previousPageData = pageData;
|
||||
}
|
||||
return mutate(data);
|
||||
}, // exclude getKey from the dependencies, which isn't allowed to change during the lifecycle
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[
|
||||
infiniteKey,
|
||||
cache,
|
||||
mutate,
|
||||
resolvePageSize
|
||||
]);
|
||||
// Use getter functions to avoid unnecessary re-renders caused by triggering
|
||||
// all the getters of the returned swr object.
|
||||
return {
|
||||
size: resolvePageSize(),
|
||||
setSize,
|
||||
mutate,
|
||||
get data () {
|
||||
return swr.data;
|
||||
},
|
||||
get error () {
|
||||
return swr.error;
|
||||
},
|
||||
get isValidating () {
|
||||
return swr.isValidating;
|
||||
},
|
||||
get isLoading () {
|
||||
return swr.isLoading;
|
||||
}
|
||||
};
|
||||
};
|
||||
const useSWRInfinite = _internal_index.withMiddleware(useSwr.useSWR, infinite);
|
||||
|
||||
exports.default = useSWRInfinite;
|
||||
exports.infinite = infinite;
|
||||
exports.unstable_serialize = unstable_serialize;
|
||||
+266
@@ -0,0 +1,266 @@
|
||||
import { useRef, useCallback } from 'react';
|
||||
import { u as useSWR } from '../use-swr-emll9s78.mjs';
|
||||
import { s as serialize, a as SWRGlobalState, o as cache, c as createCacheHelper, i as isUndefined, u as useIsomorphicLayoutEffect, U as UNDEFINED, e as isFunction } from '../config-context-ext53wcz.mjs';
|
||||
import { withMiddleware } from '../_internal/index.mjs';
|
||||
import { useSyncExternalStore } from 'use-sync-external-store/shim';
|
||||
import { INFINITE_PREFIX } from '../_internal/constants.mjs';
|
||||
|
||||
const getFirstPageKey = (getKey)=>{
|
||||
return serialize(getKey ? getKey(0, null) : null)[0];
|
||||
};
|
||||
const unstable_serialize = (getKey)=>{
|
||||
return INFINITE_PREFIX + getFirstPageKey(getKey);
|
||||
};
|
||||
|
||||
// We have to several type castings here because `useSWRInfinite` is a special
|
||||
// hook where `key` and return type are not like the normal `useSWR` types.
|
||||
const EMPTY_PROMISE = Promise.resolve();
|
||||
const infinite = (useSWRNext)=>(getKey, fn, config)=>{
|
||||
const didMountRef = useRef(false);
|
||||
const { cache: cache$1, initialSize = 1, revalidateAll = false, persistSize = false, revalidateFirstPage = true, revalidateOnMount = false, parallel = false } = config;
|
||||
const [, , , PRELOAD] = SWRGlobalState.get(cache);
|
||||
// The serialized key of the first page. This key will be used to store
|
||||
// metadata of this SWR infinite hook.
|
||||
let infiniteKey;
|
||||
try {
|
||||
infiniteKey = getFirstPageKey(getKey);
|
||||
if (infiniteKey) infiniteKey = INFINITE_PREFIX + infiniteKey;
|
||||
} catch (err) {
|
||||
// Not ready yet.
|
||||
}
|
||||
const [get, set, subscribeCache] = createCacheHelper(cache$1, infiniteKey);
|
||||
const getSnapshot = useCallback(()=>{
|
||||
const size = isUndefined(get()._l) ? initialSize : get()._l;
|
||||
return size;
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
cache$1,
|
||||
infiniteKey,
|
||||
initialSize
|
||||
]);
|
||||
useSyncExternalStore(useCallback((callback)=>{
|
||||
if (infiniteKey) return subscribeCache(infiniteKey, ()=>{
|
||||
callback();
|
||||
});
|
||||
return ()=>{};
|
||||
}, // eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[
|
||||
cache$1,
|
||||
infiniteKey
|
||||
]), getSnapshot, getSnapshot);
|
||||
const resolvePageSize = useCallback(()=>{
|
||||
const cachedPageSize = get()._l;
|
||||
return isUndefined(cachedPageSize) ? initialSize : cachedPageSize;
|
||||
// `cache` isn't allowed to change during the lifecycle
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
infiniteKey,
|
||||
initialSize
|
||||
]);
|
||||
// keep the last page size to restore it with the persistSize option
|
||||
const lastPageSizeRef = useRef(resolvePageSize());
|
||||
// When the page key changes, we reset the page size if it's not persisted
|
||||
useIsomorphicLayoutEffect(()=>{
|
||||
if (!didMountRef.current) {
|
||||
didMountRef.current = true;
|
||||
return;
|
||||
}
|
||||
if (infiniteKey) {
|
||||
// If the key has been changed, we keep the current page size if persistSize is enabled
|
||||
// Otherwise, we reset the page size to cached pageSize
|
||||
set({
|
||||
_l: persistSize ? lastPageSizeRef.current : resolvePageSize()
|
||||
});
|
||||
}
|
||||
// `initialSize` isn't allowed to change during the lifecycle
|
||||
}, [
|
||||
infiniteKey,
|
||||
cache$1
|
||||
]);
|
||||
// Needs to check didMountRef during mounting, not in the fetcher
|
||||
const shouldRevalidateOnMount = revalidateOnMount && !didMountRef.current;
|
||||
// Actual SWR hook to load all pages in one fetcher.
|
||||
const swr = useSWRNext(infiniteKey, async (key)=>{
|
||||
// get the revalidate context
|
||||
const forceRevalidateAll = get()._i;
|
||||
const shouldRevalidatePage = get()._r;
|
||||
// Capture the cache's unload generation (bumped by every `unload()`
|
||||
// call) so page responses that resolve after an unload are not
|
||||
// written back to the cleared cache.
|
||||
const state = SWRGlobalState.get(cache$1);
|
||||
const unloadGeneration = state[8];
|
||||
const unloadedDuringRequest = ()=>state[8] !== unloadGeneration;
|
||||
set({
|
||||
_r: UNDEFINED
|
||||
});
|
||||
// return an array of page data
|
||||
const data = [];
|
||||
const pageSize = resolvePageSize();
|
||||
const [getCache] = createCacheHelper(cache$1, key);
|
||||
const cacheData = getCache().data;
|
||||
const revalidators = [];
|
||||
let previousPageData = null;
|
||||
for(let i = 0; i < pageSize; ++i){
|
||||
const [pageKey, pageArg] = serialize(getKey(i, parallel ? null : previousPageData));
|
||||
if (!pageKey) {
|
||||
break;
|
||||
}
|
||||
const [getSWRCache, setSWRCache] = createCacheHelper(cache$1, pageKey);
|
||||
// Get the cached page data.
|
||||
let pageData = getSWRCache().data;
|
||||
// should fetch (or revalidate) if:
|
||||
// - `revalidateAll` is enabled
|
||||
// - `mutate()` called
|
||||
// - the cache is missing
|
||||
// - it's the first page and it's not the initial render
|
||||
// - `revalidateOnMount` is enabled and it's on mount
|
||||
// - cache for that page has changed
|
||||
const shouldFetchPage = revalidateAll || forceRevalidateAll || isUndefined(pageData) || revalidateFirstPage && !i && !isUndefined(cacheData) || shouldRevalidateOnMount || cacheData && !isUndefined(cacheData[i]) && !config.compare(cacheData[i], pageData);
|
||||
if (fn && (typeof shouldRevalidatePage === 'function' ? shouldRevalidatePage(pageData, pageArg) : shouldFetchPage)) {
|
||||
const revalidate = async ()=>{
|
||||
const hasPreloadedRequest = pageKey in PRELOAD;
|
||||
if (!hasPreloadedRequest) {
|
||||
pageData = await fn(pageArg);
|
||||
} else {
|
||||
const req = PRELOAD[pageKey];
|
||||
// delete the preload cache key before resolving it
|
||||
// in case there's an error
|
||||
delete PRELOAD[pageKey];
|
||||
// get the page data from the preload cache
|
||||
pageData = await req;
|
||||
}
|
||||
if (!unloadedDuringRequest()) {
|
||||
setSWRCache({
|
||||
data: pageData,
|
||||
_k: pageArg
|
||||
});
|
||||
}
|
||||
data[i] = pageData;
|
||||
};
|
||||
if (parallel) {
|
||||
revalidators.push(revalidate);
|
||||
} else {
|
||||
await revalidate();
|
||||
}
|
||||
} else {
|
||||
data[i] = pageData;
|
||||
}
|
||||
if (!parallel) {
|
||||
previousPageData = pageData;
|
||||
}
|
||||
}
|
||||
// flush all revalidateions in parallel
|
||||
if (parallel) {
|
||||
await Promise.all(revalidators.map((r)=>r()));
|
||||
}
|
||||
// once we executed the data fetching based on the context, clear the
|
||||
// context. Skipped after an unload so the cleared meta entry isn't
|
||||
// re-created.
|
||||
if (!unloadedDuringRequest()) {
|
||||
set({
|
||||
_i: UNDEFINED
|
||||
});
|
||||
}
|
||||
// return the data
|
||||
return data;
|
||||
}, config);
|
||||
const mutate = useCallback(// eslint-disable-next-line func-names
|
||||
function(data, opts) {
|
||||
// When passing as a boolean, it's explicitly used to disable/enable
|
||||
// revalidation.
|
||||
const options = typeof opts === 'boolean' ? {
|
||||
revalidate: opts
|
||||
} : opts || {};
|
||||
// Default to true.
|
||||
const shouldRevalidate = options.revalidate !== false;
|
||||
// It is possible that the key is still falsy.
|
||||
if (!infiniteKey) return EMPTY_PROMISE;
|
||||
if (shouldRevalidate) {
|
||||
if (!isUndefined(data)) {
|
||||
// We only revalidate the pages that are changed
|
||||
set({
|
||||
_i: false,
|
||||
_r: options.revalidate
|
||||
});
|
||||
} else {
|
||||
// Calling `mutate()`, we revalidate all pages
|
||||
set({
|
||||
_i: true,
|
||||
_r: options.revalidate
|
||||
});
|
||||
}
|
||||
}
|
||||
return arguments.length ? swr.mutate(data, {
|
||||
...options,
|
||||
revalidate: shouldRevalidate
|
||||
}) : swr.mutate();
|
||||
}, // swr.mutate is always the same reference
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[
|
||||
infiniteKey,
|
||||
cache$1
|
||||
]);
|
||||
// Extend the SWR API
|
||||
const setSize = useCallback((arg)=>{
|
||||
// It is possible that the key is still falsy.
|
||||
if (!infiniteKey) return EMPTY_PROMISE;
|
||||
const [, changeSize] = createCacheHelper(cache$1, infiniteKey);
|
||||
let size;
|
||||
if (isFunction(arg)) {
|
||||
size = arg(resolvePageSize());
|
||||
} else if (typeof arg == 'number') {
|
||||
size = arg;
|
||||
}
|
||||
if (typeof size != 'number') return EMPTY_PROMISE;
|
||||
changeSize({
|
||||
_l: size
|
||||
});
|
||||
lastPageSizeRef.current = size;
|
||||
// Calculate the page data after the size change.
|
||||
const data = [];
|
||||
const [getInfiniteCache] = createCacheHelper(cache$1, infiniteKey);
|
||||
let previousPageData = null;
|
||||
for(let i = 0; i < size; ++i){
|
||||
const [pageKey] = serialize(getKey(i, previousPageData));
|
||||
const [getCache] = createCacheHelper(cache$1, pageKey);
|
||||
// Get the cached page data.
|
||||
const pageData = pageKey ? getCache().data : UNDEFINED;
|
||||
// Call `mutate` with infinte cache data if we can't get it from the page cache.
|
||||
if (isUndefined(pageData)) {
|
||||
return mutate(getInfiniteCache().data);
|
||||
}
|
||||
data.push(pageData);
|
||||
previousPageData = pageData;
|
||||
}
|
||||
return mutate(data);
|
||||
}, // exclude getKey from the dependencies, which isn't allowed to change during the lifecycle
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[
|
||||
infiniteKey,
|
||||
cache$1,
|
||||
mutate,
|
||||
resolvePageSize
|
||||
]);
|
||||
// Use getter functions to avoid unnecessary re-renders caused by triggering
|
||||
// all the getters of the returned swr object.
|
||||
return {
|
||||
size: resolvePageSize(),
|
||||
setSize,
|
||||
mutate,
|
||||
get data () {
|
||||
return swr.data;
|
||||
},
|
||||
get error () {
|
||||
return swr.error;
|
||||
},
|
||||
get isValidating () {
|
||||
return swr.isValidating;
|
||||
},
|
||||
get isLoading () {
|
||||
return swr.isLoading;
|
||||
}
|
||||
};
|
||||
};
|
||||
const useSWRInfinite = withMiddleware(useSWR, infinite);
|
||||
|
||||
export { useSWRInfinite as default, infinite, unstable_serialize };
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { s as serialize } from '../serialize-hqt5osie.mjs';
|
||||
import { INFINITE_PREFIX } from '../_internal/constants.mjs';
|
||||
|
||||
const getFirstPageKey = (getKey)=>{
|
||||
return serialize(getKey ? getKey(0, null) : null)[0];
|
||||
};
|
||||
const unstable_serialize = (getKey)=>{
|
||||
return INFINITE_PREFIX + getFirstPageKey(getKey);
|
||||
};
|
||||
|
||||
export { unstable_serialize };
|
||||
Reference in new issue
Block a user