Skip to main content

Function: usePaginationWithSearch()

@arolariu/website


@arolariu/website / hooks/usePagination / usePaginationWithSearch

Function: usePaginationWithSearch()

usePaginationWithSearch<T>(params): PaginationWithSearchOutputType<T>

Defined in: hooks/usePagination.tsx:145

Provides pagination state and controls with integrated search filtering.

Type Parameters

T

T

The type of items being paginated

Parameters

params

PaginationWithSearchInputType<T>

Hook configuration

Returns

PaginationWithSearchOutputType<T>

Pagination state and control functions

Remarks

Rendering Context: Client Component hook (requires "use client" directive).

Search Behavior:

  • When searchQuery is provided, filters items using JSON.stringify + case-insensitive matching
  • Automatically resets to page 1 when search query changes (derived, no state mutation)
  • Empty or whitespace-only queries return all items unfiltered

Pagination Logic:

  • Pages are 1-indexed (page 1 is the first page)
  • currentPage is derived and automatically clamped to [1, totalPages]
  • Requesting page 999 when only 5 pages exist will display page 5
  • totalPages minimum value is 1 (even for empty arrays)

Performance Optimizations:

  • Uses useMemo to prevent unnecessary recalculations
  • Uses useCallback for stable function references
  • No unnecessary effects or state updates
  • Derived state pattern (no sync between state variables)

Generic Pagination:

  • The paginate function can paginate any array type, not just T
  • Useful for paginating derived/transformed data

State Management:

  • Internal state tracks "requested page" (may be out of bounds)
  • Derived currentPage is always valid (clamped)
  • This prevents state sync issues when items/filters change

Examples

function InvoiceTable({invoices}: {invoices: Invoice[]}) {
const [searchTerm, setSearchTerm] = useState("");

const {
paginatedItems,
currentPage,
setCurrentPage,
totalPages,
pageSize,
setPageSize,
} = usePaginationWithSearch({
items: invoices,
initialPageSize: 10,
searchQuery: searchTerm,
});

return (
<>
<SearchInput value={searchTerm} onChange={setSearchTerm} />
<Table>
{paginatedItems.map((invoice) => (
<InvoiceRow key={invoice.id} invoice={invoice} />
))}
</Table>
<Pagination
currentPage={currentPage}
totalPages={totalPages}
onPageChange={setCurrentPage}
/>
</>
);
}
// Using generic paginate function for transformed data
function MerchantList() {
const {paginate} = usePaginationWithSearch({items: merchants});

const sortedMerchants = merchants.sort((a, b) => a.name.localeCompare(b.name));
const paginatedSortedMerchants = paginate(sortedMerchants);

return <MerchantGrid merchants={paginatedSortedMerchants} />;
}

See

React Derived State Pattern

// was this page useful?