@resourge/react-fetch
Version:
[](LICENSE)
243 lines (240 loc) • 6.94 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, 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