Skip to content

Commit

Permalink
fix(useInfiniteScroll): fix isLoading & isLoadDone state not upda…
Browse files Browse the repository at this point in the history
…te expectedly
  • Loading branch information
vikiboss committed Aug 29, 2024
1 parent 701c7d0 commit 3ef21b9
Showing 1 changed file with 21 additions and 16 deletions.
37 changes: 21 additions & 16 deletions src/use-infinite-scroll/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export interface UseInfiniteScrollReturns {
/**
* calculate the current scroll position to determine whether to load more
*/
calculate(event: Event): void
calculate(): void
}

/**
Expand All @@ -80,42 +80,47 @@ export function useInfiniteScroll<R = any, T extends HTMLElement = HTMLElement>(
const [state, setState] = useRafState({ isLoading: false, isLoadDone: false }, { deep: true })
const latest = useLatest({ state, direction, onScroll, onLoadMore, interval })

const calculate = useStableFn(async (event: Event) => {
const { state, direction, onLoadMore, interval, onScroll } = latest.current
const calculate = useStableFn(async () => {
if (!canLoadMore(previousReturn.current)) return

onScroll?.(event)
const { state, direction, onLoadMore, interval } = latest.current

if (!canLoadMore(previousReturn.current)) {
return setState({ ...state, isLoadDone: true })
}

if (!el.current) return
if (!el.current || state.isLoading) return

const { scrollHeight, scrollTop, clientHeight, scrollWidth, clientWidth } = el.current

const isYScroll = direction === 'bottom' || direction === 'top'
const isScrollNarrower = isYScroll ? scrollHeight <= clientHeight : scrollWidth <= clientWidth
const isAlmostBottom = scrollHeight - scrollTop <= clientHeight + distance

if (state.isLoading) return

if (!isScrollNarrower && !isAlmostBottom) return

setState({ ...state, isLoading: true })
setState({ isLoadDone: false, isLoading: true })

const [res, _] = await Promise.all([
const [result, _] = await Promise.all([
onLoadMore(previousReturn.current),
new Promise((resolve) => setTimeout(resolve, interval)),
])

setState({ ...latest.current.state, isLoading: false })
previousReturn.current = result

previousReturn.current = res
setState({
isLoading: false,
isLoadDone: !canLoadMore(previousReturn.current),
})
})

useMount(immediate && calculate)

useEventListener(el, 'scroll', calculate, { passive: true })
useEventListener(
el,
'scroll',
(event) => {
latest.current.onScroll?.(event)
calculate()
},
{ passive: true },
)

return {
...state,
Expand Down

0 comments on commit 3ef21b9

Please sign in to comment.