fix: stabilize usePaginationParams to prevent infinite re-render loop

allowedPageSizes array was recreated every render as a useMemo dep,
causing infinite updates. Use useRef to stabilize the reference.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Michael Chihlas
2026-02-20 21:29:12 -05:00
parent 4d4ba7acac
commit 0b6d5727c9

View File

@@ -1,5 +1,5 @@
import { useSearchParams } from 'react-router-dom'
import { useCallback, useMemo } from 'react'
import { useCallback, useMemo, useRef } from 'react'
type PageSize = number | 'all'
@@ -8,8 +8,15 @@ interface UsePaginationParamsOptions {
allowedPageSizes?: PageSize[]
}
const DEFAULT_ALLOWED: PageSize[] = [10, 25, 50, 'all']
export function usePaginationParams(options: UsePaginationParamsOptions = {}) {
const { defaultPageSize = 10, allowedPageSizes = [10, 25, 50, 'all'] } = options
const { defaultPageSize = 10, allowedPageSizes = DEFAULT_ALLOWED } = options
// Stabilize the array reference to avoid re-render loops
const allowedRef = useRef(allowedPageSizes)
allowedRef.current = allowedPageSizes
const [searchParams, setSearchParams] = useSearchParams()
const page = useMemo(() => {
@@ -20,11 +27,11 @@ export function usePaginationParams(options: UsePaginationParamsOptions = {}) {
const pageSize = useMemo((): PageSize => {
const raw = searchParams.get('size')
if (raw === 'all' && allowedPageSizes.includes('all')) return 'all'
if (raw === 'all' && allowedRef.current.includes('all')) return 'all'
const n = raw ? parseInt(raw, 10) : defaultPageSize
if (Number.isFinite(n) && allowedPageSizes.includes(n)) return n
if (Number.isFinite(n) && allowedRef.current.includes(n)) return n
return defaultPageSize
}, [searchParams, defaultPageSize, allowedPageSizes])
}, [searchParams, defaultPageSize])
const setPage = useCallback(
(newPage: number) => {