Tanstack React Table分页点击后自动重置问题求助
问题排查:TanStack React Table分页时pageIndex自动重置为0
核心问题分析
初始
count为0导致pageCount计算错误:
你的pageCount通过Math.ceil(count / pagination.pageSize)计算,而初始状态下count=0,会直接导致pageCount=0。TanStack React Table内部会做边界校验:当pageIndex大于等于pageCount时,会自动将pageIndex重置为0。所以点击下一页时,pageIndex先变为1,但因pageCount=0触发校验规则,立刻被重置回0。Supabase客户端重复创建:
组件每次渲染都会调用createClient()生成新的客户端实例,既浪费资源也可能引发请求异常,需要缓存该实例。表格渲染代码缺失:
返回的JSX中{...table}是无效语法,必须用flexRender正确渲染表头和表体,否则表格无法正常渲染,也会影响分页组件的交互逻辑。
修复方案
1. 修正pageCount计算逻辑
修改useReactTable配置中的pageCount,处理count为0的边界情况:
pageCount: count ? Math.ceil(count / pagination.pageSize) : 1,
初始状态下pageCount设为1,避免触发内部重置逻辑,等数据加载完成后count更新,pageCount会自动修正。
2. 缓存Supabase客户端
用useMemo缓存客户端实例,避免重复创建:
const supabase = useMemo(() => createClient(), []);
3. 补全表格渲染代码
替换返回中的{...table}为标准表格渲染结构:
<Table> <TableHeader> {table.getHeaderGroups().map(headerGroup => ( <TableRow key={headerGroup.id}> {headerGroup.headers.map(header => ( <TableHead key={header.id}> {header.isPlaceholder ? null : flexRender( header.column.columnDef.header, header.getContext() )} </TableHead> ))} </TableRow> ))} </TableHeader> <TableBody> {table.getRowModel().rows.map(row => ( <TableRow key={row.id} data-state={row.getIsSelected() ? 'selected' : undefined} > {row.getVisibleCells().map(cell => ( <TableCell key={cell.id}> {flexRender(cell.column.columnDef.cell, cell.getContext())} </TableCell> ))} </TableRow> ))} </TableBody> </Table>
4. 优化请求触发逻辑(可选)
去掉冗余的mounted状态,直接用useEffect触发初始数据请求:
useEffect(() => { fetchData(); }, []);
关键修复后代码片段
function DataTable({ columns }) { const [data, setData] = useState([]); const [count, setCount] = useState(0); const [rowSelection, setRowSelection] = useState({}); const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 15, }); const supabase = useMemo(() => createClient(), []); const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel(), onRowSelectionChange: setRowSelection, pageCount: count ? Math.ceil(count / pagination.pageSize) : 1, onPaginationChange: setPagination, getPaginationRowModel: getPaginationRowModel(), state: { rowSelection, pagination, }, }); useEffect(() => { async function fetchData() { const from = pagination.pageIndex * pagination.pageSize; const { data, count, error } = await supabase .from("contacts") .select("*", { count: "exact" }) .order("created_at", { ascending: false }) .range(from, from + pagination.pageSize - 1); if (error) { console.error(error); return; } setCount(count || 0); setData(data || []); } fetchData(); }, [pagination.pageIndex, pagination.pageSize, supabase]); return ( <div className="h-full flex flex-col flex-1 overflow-x-auto"> <div className="flex-grow overflow-x-auto min-h-0"> <Table> <TableHeader> {table.getHeaderGroups().map(headerGroup => ( <TableRow key={headerGroup.id}> {headerGroup.headers.map(header => ( <TableHead key={header.id}> {header.isPlaceholder ? null : flexRender( header.column.columnDef.header, header.getContext() )} </TableHead> ))} </TableRow> ))} </TableHeader> <TableBody> {table.getRowModel().rows.map(row => ( <TableRow key={row.id} data-state={row.getIsSelected() ? 'selected' : undefined} > {row.getVisibleCells().map(cell => ( <TableCell key={cell.id}> {flexRender(cell.column.columnDef.cell, cell.getContext())} </TableCell> ))} </TableRow> ))} </TableBody> </Table> </div> <div className="select-none bg-background"> <PaginationFooter table={table} /> </div> </div> ); }
内容的提问来源于stack exchange,提问作者David Henry
相关产品推荐
相关产品推荐

