Skip to content

Instantly share code, notes, and snippets.

@lukeramsden
Created January 18, 2025 20:30
Show Gist options
  • Save lukeramsden/003cf887ab29a7faeb09d8f0c23a4b19 to your computer and use it in GitHub Desktop.
Save lukeramsden/003cf887ab29a7faeb09d8f0c23a4b19 to your computer and use it in GitHub Desktop.
usePaginatedFetch
import { useCallback, useMemo, useRef, useState } from "react"
import { produce } from "immer"
interface PaginatedFetchState {
pageSize: number
startingAfter: string | undefined
endingBefore: string | undefined
direction: 'forward' | 'backward'
isOnFirstPage: boolean
}
export function usePaginatedFetch<T extends { page: { hasMore: boolean } }>(fetchHook: (pagination: PaginatedFetchState) => T, _getFirstItemId: (items: T) => string, _getLastItemId: (items: T) => string) {
const getFirstItemId = useRef(_getFirstItemId).current
const getLastItemId = useRef(_getLastItemId).current
const [pagination, setPagination] = useState<PaginatedFetchState>({ pageSize: 10, startingAfter: undefined, endingBefore: undefined, direction: 'forward', isOnFirstPage: true })
const data = fetchHook(pagination)
const tablePageSize = pagination.pageSize
const setTablePageSize = useCallback((pageSize: number): void => {
setPagination(produce(draft => {
draft.pageSize = pageSize
draft.isOnFirstPage = true
draft.startingAfter = undefined
draft.endingBefore = undefined
draft.direction = 'forward'
}))
}, [pagination])
const canGoBackwards = pagination.isOnFirstPage ? false : pagination.direction === 'backward' ? data.page.hasMore : true;
const canGoForwards = pagination.direction === 'forward' ? data.page.hasMore : true;
const goBackwards = useCallback(() => {
setPagination(produce(draft => {
draft.startingAfter = undefined
draft.endingBefore = getFirstItemId(data)
draft.direction = 'backward'
draft.isOnFirstPage = false
}))
}, [data])
const goForwards = useCallback(() => {
setPagination(produce(draft => {
draft.startingAfter = getLastItemId(data)
draft.endingBefore = undefined
draft.direction = 'forward'
draft.isOnFirstPage = false
}))
}, [data])
return useMemo(() => ({
data,
tablePageSize,
setTablePageSize,
canGoBackwards,
canGoForwards,
goBackwards,
goForwards
}), [data, tablePageSize, setTablePageSize, canGoBackwards, canGoForwards, goBackwards, goForwards])
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment