import { ColumnDef, OnChangeFn, PaginationState, Row, getCoreRowModel, getPaginationRowModel, useReactTable, } from "@tanstack/react-table" import { useEffect, useMemo, useState } from "react" import { useSearchParams } from "react-router-dom" type UseDataTableProps = { data?: TData[] columns: ColumnDef[] count?: number pageSize?: number enableRowSelection?: boolean | ((row: Row) => boolean) enablePagination?: boolean getRowId?: (original: TData, index: number) => string meta?: Record prefix?: string } export const useDataTable = ({ data = [], columns, count = 0, pageSize: _pageSize = 20, enablePagination = true, enableRowSelection = false, getRowId, meta, prefix, }: UseDataTableProps) => { const [searchParams, setSearchParams] = useSearchParams() const offsetKey = `${prefix ? `${prefix}_` : ""}offset` const offset = searchParams.get(offsetKey) const [{ pageIndex, pageSize }, setPagination] = useState({ pageIndex: offset ? Math.ceil(Number(offset) / _pageSize) : 0, pageSize: _pageSize, }) const pagination = useMemo( () => ({ pageIndex, pageSize, }), [pageIndex, pageSize] ) const [rowSelection, setRowSelection] = useState({}) useEffect(() => { if (!enablePagination) { return } const index = offset ? Math.ceil(Number(offset) / _pageSize) : 0 if (index === pageIndex) { return } setPagination((prev) => ({ ...prev, pageIndex: index, })) }, [offset, enablePagination, _pageSize, pageIndex]) const onPaginationChange = ( updater: (old: PaginationState) => PaginationState ) => { const state = updater(pagination) const { pageIndex, pageSize } = state setSearchParams((prev) => { if (!pageIndex) { prev.delete(offsetKey) return prev } const newSearch = new URLSearchParams(prev) newSearch.set(offsetKey, String(pageIndex * pageSize)) return newSearch }) setPagination(state) return state } const table = useReactTable({ data, columns, state: { rowSelection, pagination: enablePagination ? pagination : undefined, }, pageCount: Math.ceil((count ?? 0) / pageSize), enableRowSelection, getRowId, onRowSelectionChange: enableRowSelection ? setRowSelection : undefined, onPaginationChange: enablePagination ? (onPaginationChange as OnChangeFn) : undefined, getCoreRowModel: getCoreRowModel(), getPaginationRowModel: enablePagination ? getPaginationRowModel() : undefined, manualPagination: enablePagination ? true : undefined, meta, }) return { table } }