UNPKG

@resourge/react-fetch

Version:

[![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)

160 lines (157 loc) 4.3 kB
/** * react-fetch v1.43.1 * * 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, useEffect } 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({}); useEffect(() => { preloadRef.current = {}; }, deps); function willPreload(page) { var _preload$timeout; return preload !== false && preloadRef.current[page] && Date.now() - preloadRef.current[page].date <= ((_preload$timeout = preload.timeout) != null ? _preload$timeout : ONE_MINUTE_IN_MILLISECOND); } async function _getMethod(metadata) { const page = metadata.pagination.page; if (willPreload(page)) { return preloadRef.current[page].data; } const data = await method(metadata); preloadRef.current[page] = { date: Date.now(), data }; return preloadRef.current[page].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 } }; preloadRef.current = {}; const maxPerPage = typeof preload === 'object' ? preload.maxPerPage : undefined; const { data, totalItems } = await (!maxPerPage ? _getMethod(_metadata) : getMultipleMethod(_metadata, Math.min(maxPerPage, _metadata.pagination.perPage))); 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 page = index + initialPage; preloadRef.current[page] = { 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