UNPKG

@resourge/react-fetch

Version:

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

243 lines (240 loc) 6.94 kB
/** * 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, useEffect } from 'react'; import { DEFAULT_PAGE, DEFAULT_PER_PAGE } from '../utils/constants'; import { createProxy } from '../utils/createProxy'; import { calculateTotalPages } from '../utils/utils'; import { useFetch } from './useFetch'; import { useFilterSearchParams } from './useFilterSearchParams'; import { useIsOnline } from './useIsOnline'; import { usePreload } from './usePreload'; const useInfiniteLoading = (method, { initialState, filter: defaultFilter = {}, sort: defaultSort, hash, deps = [], initialPage = DEFAULT_PAGE, initialPerPage = DEFAULT_PER_PAGE, scrollRestoration, preload, fId, ...config }) => { const isOnline = useIsOnline(); const _scrollRestoration = scrollRestoration; if (process.env.NODE_ENV === 'development') { if (_scrollRestoration && !_scrollRestoration.getPage) { throw new Error("'scrollRestoration' needs to come from 'useInfiniteScrollRestoration'. 'scrollRestoration' from 'useScrollRestoration' doesn't work"); } } const internalDataRef = useRef({ isFirstTime: true, isLoading: false, data: [], isLast: false, isLastIncomplete: false }); const { willPreload, getMethod, getRestoreMethod, preloadRef } = usePreload({ method, preload, initialPage, deps }); async function fetchRestoredData(metadata, restoration) { const { totalItems } = await getRestoreMethod(metadata, { page: restoration.page, perPage: restoration.perPage }, (index, data) => { internalDataRef.current.data[index] = data.splice(index, restoration.perPage); }); return { page: restoration.page, totalItems }; } async function fetchDataMethod(metadata) { if (internalDataRef.current.isFirstTime && _scrollRestoration) { const scrollRestorationData = _scrollRestoration.getPage(); if (scrollRestorationData.perPage !== undefined && scrollRestorationData.page !== undefined) { return await fetchRestoredData(metadata, { page: scrollRestorationData.page, perPage: scrollRestorationData.perPage }); } } const { data, totalItems } = await getMethod(metadata); internalDataRef.current.data[metadata.pagination.page] = data; return { page: metadata.pagination.page, totalItems }; } const filterKeysRef = useRef({ keys: new Set() }); const fetchData = useFetch(async (metadata = { pagination, filter, sort }, whatChanged) => { if (whatChanged && whatChanged.size && !(whatChanged.size === 1 && whatChanged.has('pagination'))) { internalDataRef.current.data = []; } internalDataRef.current.isLoading = true; const { page, totalItems } = await fetchDataMethod(createProxy(metadata, filterKeysRef.current)); internalDataRef.current.isFirstTime = false; changeTotalPages(totalItems != null ? totalItems : 0); pagination.page = page; const newData = internalDataRef.current.data.flat(); if (_scrollRestoration) { _scrollRestoration.setPage(pagination.page, pagination.perPage); } const inInComplete = newData.length !== internalDataRef.current.data.length * pagination.perPage; internalDataRef.current.isLast = newData.length === totalItems; internalDataRef.current.isLastIncomplete = internalDataRef.current.isLast && inInComplete; internalDataRef.current.isLoading = false; return newData; }, { initialState, ...config, scrollRestoration, deps }); const { pagination, filter, sort, setFilter, sortTable, setParams } = useFilterSearchParams({ fetch: fetchData.fetch, preloadRef, defaultFilter, defaultSort, initialPage, initialPerPage, hash, deps, fId, filterKeysRef }); useEffect(() => { internalDataRef.current.data = []; pagination.page = initialPage; }, [isOnline, ...deps]); const changePage = page => { pagination.page = page; fetchData.fetch(); }; const changeTotalPages = totalItems => { const totalPages = calculateTotalPages(pagination.perPage, totalItems); pagination.totalPages = totalPages != null ? totalPages : pagination.totalPages; pagination.totalItems = totalItems; if (totalPages < pagination.page) { changePage(initialPage); } }; return { preload: () => { getMethod({ filter, sort, pagination: { ...pagination, page: pagination.page + 1 } }); }, isLast: internalDataRef.current.isLast, isLastIncomplete: internalDataRef.current.isLastIncomplete, loadMore: async () => { if (internalDataRef.current.isLoading) { return; } if (!internalDataRef.current.isLastIncomplete) { changePage(pagination.page + 1); } if (willPreload(pagination.page)) { return; } const { totalItems } = await fetchRestoredData({ pagination, sort, filter }, pagination); changeTotalPages(totalItems != null ? totalItems : 0); fetchData.setFetchState(internalDataRef.current.data.flat()); }, data: fetchData.data, get error() { return fetchData.error; }, get isLoading() { return fetchData.isLoading; }, setPaginationState: fetchData.setFetchState, fetch: () => { preloadRef.current = {}; return fetchData.fetch(); }, pagination, sort, filter, changeItemsPerPage: perPage => { pagination.perPage = perPage; pagination.page = initialPage; internalDataRef.current.data = []; fetchData.fetch(); }, setFilter, sortTable, reset: (value = {}) => { var _value$pagination$per, _value$pagination, _value$pagination$per2, _value$pagination2, _value$sort; pagination.perPage = (_value$pagination$per = (_value$pagination = value.pagination) == null ? void 0 : _value$pagination.perPage) != null ? _value$pagination$per : initialPerPage; pagination.page = (_value$pagination$per2 = (_value$pagination2 = value.pagination) == null ? void 0 : _value$pagination2.perPage) != null ? _value$pagination$per2 : initialPage; setParams({ sort: (_value$sort = value.sort) != null ? _value$sort : defaultSort, ...defaultFilter, ...filter }); }, get context() { return this; }, toJSON() { return { ...this, get context() { return 'To Prevent circular dependency'; } }; } }; }; export { useInfiniteLoading }; //# sourceMappingURL=useInfiniteLoading.js.map