99 lines
2.4 KiB
TypeScript
99 lines
2.4 KiB
TypeScript
import { RefObject, useEffect, useRef, useState } from 'react';
|
|
|
|
interface FetchFunction<T> {
|
|
(page: number): Promise<T[]>;
|
|
}
|
|
|
|
const useLoadOnScroll = <T>(executeFetch: FetchFunction<T>) => {
|
|
const [data, setData] = useState<T[]>([]);
|
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
|
const [page, setPage] = useState<number>(1);
|
|
const [listener, setListener] = useState<number>(1);
|
|
const [lastPage, setLastPage] = useState<boolean>(false);
|
|
|
|
const fetchData = async (isSearch?: boolean) => {
|
|
if (!lastPage || isSearch === true)
|
|
if (isLoading === false) {
|
|
setIsLoading(true);
|
|
if (isSearch === true) {
|
|
const newData = await executeFetch(1);
|
|
if (newData.length > 0) {
|
|
setData(newData);
|
|
setPage((prevPage) => 2);
|
|
} else {
|
|
setLastPage(true);
|
|
setData([]);
|
|
}
|
|
} else {
|
|
const newData = await executeFetch(page);
|
|
if (newData.length > 0) {
|
|
setData((prevData) => [...prevData, ...newData]);
|
|
setPage((prevPage) => prevPage + 1);
|
|
} else {
|
|
setLastPage(true);
|
|
}
|
|
}
|
|
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
const refetchData = () => {
|
|
setPage(1);
|
|
setListener((prev) => prev + 1);
|
|
};
|
|
|
|
const resetLastPage = () => {
|
|
setLastPage(false);
|
|
};
|
|
|
|
useEffect(() => {
|
|
fetchData();
|
|
}, [listener]);
|
|
|
|
// useEffect(() => {
|
|
// if (data.length === 0) {
|
|
// fetchData();
|
|
// }
|
|
// }, [data]);
|
|
|
|
const handleScroll = () => {
|
|
const { scrollTop, clientHeight, scrollHeight } = document.documentElement;
|
|
|
|
if (scrollTop + clientHeight >= scrollHeight - 1) {
|
|
setListener((prevListener) => prevListener + 1);
|
|
}
|
|
};
|
|
|
|
const resetSearch = () => {
|
|
console.log('reset search');
|
|
fetchData(true);
|
|
resetLastPage();
|
|
};
|
|
|
|
useEffect(() => {
|
|
window.addEventListener('scroll', handleScroll);
|
|
|
|
return () => {
|
|
window.removeEventListener('scroll', handleScroll);
|
|
};
|
|
}, []);
|
|
|
|
const onClose = () => {
|
|
setData([]);
|
|
setPage(1);
|
|
setLastPage(false);
|
|
};
|
|
|
|
const onOpen = () => {
|
|
setData([]);
|
|
setLastPage(false);
|
|
fetchData(true);
|
|
};
|
|
|
|
// setData and setPage to reset when the dialog closed
|
|
return { data, isLoading, setPage, setData, resetSearch, resetLastPage, onClose, onOpen, refetchData };
|
|
};
|
|
|
|
export default useLoadOnScroll;
|