@resourge/react-fetch
Version:
[](LICENSE)
162 lines (159 loc) • 4.35 kB
JavaScript
/**
* react-fetch v1.41.3
*
* Copyright (c) resourge.
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
import { useRef } from 'react';
import { IS_DEV } from '../utils/constants';
import { calculateTotalPages } from '../utils/utils';
const ONE_MINUTE_IN_MILLISECOND = 1 * 60 * 1000;
const usePreload = ({
method,
preload = {},
initialPage,
deps
}) => {
if (IS_DEV) {
if (typeof preload === 'object' && preload.maxPerPage && !Number.isInteger(preload.maxPerPage)) {
throw new Error('`maxPerPage` needs to be integer');
}
}
const preloadRef = useRef({});
function getKey(page) {
return `${page}_${deps.length ? JSON.stringify(deps) : ''}`;
}
function willPreload(page) {
var _preload$timeout;
const key = getKey(page);
return preload !== false && preloadRef.current[key] && Date.now() - preloadRef.current[key].date <= ((_preload$timeout = preload.timeout) != null ? _preload$timeout : ONE_MINUTE_IN_MILLISECOND);
}
async function _getMethod(metadata) {
const page = metadata.pagination.page;
const key = getKey(page);
if (willPreload(page)) {
return preloadRef.current[key].data;
}
const data = await method(metadata);
preloadRef.current[key] = {
date: Date.now(),
data
};
return preloadRef.current[key].data;
}
function preloadMethod(metadata, res) {
if (preload === false) {
return;
}
if (preload.previous !== false) {
const previousPage = metadata.pagination.page - 1;
if (previousPage >= initialPage) {
_getMethod({
...metadata,
pagination: {
...metadata.pagination,
page: previousPage
}
});
}
}
if (preload.next !== false) {
const nextPage = metadata.pagination.page + 1;
const totalPages = calculateTotalPages(metadata.pagination.perPage, res.totalItems);
if (initialPage ? nextPage <= totalPages : nextPage < totalPages) {
_getMethod({
...metadata,
pagination: {
...metadata.pagination,
page: nextPage
}
});
}
}
}
async function getMethod(metadata) {
const res = await _getMethod(metadata);
preloadMethod(metadata, res);
return res;
}
async function getMultipleMethod(metadata, maxPerPage) {
const results = await Promise.all(Array.from({
length: Math.ceil(metadata.pagination.perPage / maxPerPage)
}, (_, index) => _getMethod({
...metadata,
pagination: {
...metadata.pagination,
page: index + initialPage,
perPage: maxPerPage
}
})));
const totalItems = results[0].totalItems;
const data = results.flatMap(({
data
}) => data);
return {
totalItems,
data
};
}
async function getRestoreMethod(metadata, pagination, onData) {
const _metadata = {
...metadata,
pagination: {
...metadata.pagination,
page: initialPage,
perPage: pagination.perPage * (pagination.page + 1)
}
};
preloadRef.current = {};
const maxPerPage = typeof preload === 'object' ? preload.maxPerPage : undefined;
const {
data,
totalItems
} = await (!maxPerPage ? _getMethod(_metadata) : getMultipleMethod(_metadata, maxPerPage));
const date = Date.now();
let lastPage = initialPage;
Array.from({
length: Math.ceil(data.length / metadata.pagination.perPage)
}, (_, index) => {
const newIndex = index + initialPage;
lastPage = newIndex;
const newData = data.splice(index, metadata.pagination.perPage);
onData && onData(newIndex, newData);
const key = getKey(index + initialPage);
preloadRef.current[key] = {
data: {
data: newData,
totalItems
},
date
};
return undefined;
});
preloadMethod({
...metadata,
pagination: {
...metadata.pagination,
page: lastPage
}
}, {
data,
totalItems
});
return {
totalItems
};
}
return {
willPreload,
getMethod,
getRestoreMethod,
preloadRef
};
};
export { usePreload };
//# sourceMappingURL=usePreload.js.map