126 lines
3.6 KiB
JavaScript

import { useCallback } from 'react'
import config from '../../../config'
import loglevel from 'loglevel'
const logger = loglevel.getLogger('useTableScroll')
logger.setLevel(config.logLevel)
export const useTableScroll = ({
lazyLoading,
hasMore,
hasPrevious,
currentLoadedPageNumber,
loadingPages,
createSkeletonData,
fetchData,
setCurrentLoadedPageNumber,
setLazyLoading,
setPages,
setLoadedPages,
loadedPages
}) => {
const handleScroll = useCallback(
(e) => {
const { target } = e
const scrollHeight = target.scrollHeight
const scrollTop = target.scrollTop
const clientHeight = target.clientHeight
// Load more data when scrolling down
if (
scrollHeight - scrollTop - clientHeight < 100 &&
!lazyLoading &&
hasMore
) {
logger.debug(loadedPages)
const lowestPage = Math.max(...loadedPages)
const nextPage = lowestPage + 1
if (!loadingPages.has(nextPage)) {
setLazyLoading(true)
setCurrentLoadedPageNumber(nextPage)
setPages((prev) => {
const filteredPages = prev.map((page) => ({
...page,
items: page.items.filter((item) => !item.isSkeleton)
}))
const relevantPages = filteredPages.slice(-2)
logger.debug('Pages after scroll down:', {
current: currentLoadedPageNumber,
next: nextPage,
keeping: relevantPages.map((p) => p.pageNum)
})
return [
...relevantPages,
{ pageNum: nextPage, items: createSkeletonData() }
]
})
// Adjust scroll position to center the new content
setTimeout(() => {
const newScrollTop = (target.scrollHeight - clientHeight) / 2
target.scrollTo({ top: newScrollTop })
}, 0)
fetchData(nextPage, true)
}
}
// Load previous data when scrolling up
if (
scrollTop < 100 &&
!lazyLoading &&
hasPrevious &&
currentLoadedPageNumber > 1
) {
const lowestPage = Math.min(...loadedPages)
const prevPage = lowestPage - 1
if (!loadingPages.has(prevPage)) {
setLazyLoading(true)
setCurrentLoadedPageNumber(prevPage)
setPages((prev) => {
const relevantPages = filteredPages.slice(0, 1)
const filteredPages = prev.map((page) => ({
...page,
items: page.items.filter((item) => !item.isSkeleton)
}))
logger.debug('Pages after scroll up:', {
current: currentLoadedPageNumber,
prev: prevPage,
keeping: relevantPages.map((p) => p.pageNum)
})
return [
{ pageNum: prevPage, items: createSkeletonData() },
...relevantPages
]
})
setLoadedPages((prev) => {
const relevantPages = prev.slice(0, 1)
return [prevPage, ...relevantPages]
})
// Adjust scroll position to center the new content
setTimeout(() => {
const newScrollTop = (target.scrollHeight - clientHeight) / 2
target.scrollTo({ top: newScrollTop })
}, 0)
fetchData(prevPage, false, true)
}
}
},
[
lazyLoading,
hasMore,
hasPrevious,
currentLoadedPageNumber,
loadingPages,
createSkeletonData,
fetchData,
setCurrentLoadedPageNumber,
setLazyLoading,
setPages,
setLoadedPages,
loadedPages
]
)
return { handleScroll }
}