Files
2026-10-19 16:04:17 +02:00

271 lines
12 KiB
JavaScript

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;