You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 05:22:18