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

react-table使用分页功能时UI重渲染、页面刷新问题如何解决?

问题修复方案

核心原因排查

点击分页触发页面刷新、useEffect重执行、分页状态重置,主要是以下3个常见原因导致:

  • 分页按钮未指定type属性,外层存在form标签时默认触发submit提交行为,导致页面整体刷新
  • react-table配置项未做缓存,每次渲染生成新的配置实例,触发useTable内部状态重置
  • 未关闭react-table默认的autoResetPage行为,数据变更时自动重置分页状态

具体修改步骤

1. 给所有分页按钮添加type属性

浏览器默认<button>的type值为submit,如果组件外层包裹了<form>标签,点击按钮会触发表单提交导致页面刷新,给所有分页按钮加上type="button"即可:

// 所有分页按钮统一修改
<button type="button" onClick={() => gotoPage(0)} disabled={!canPreviousPage}>
  {'<<'}
</button>{' '}
<button type="button" onClick={() => previousPage()} disabled={!canPreviousPage}>
  {'<'}
</button>{' '}
<button type="button" onClick={() => nextPage()} disabled={!canNextPage}>
  {'>'}
</button>{' '}
<button type="button" onClick={() => gotoPage(pageCount - 1)} disabled={!canNextPage}>
  {'>>'}
</button>

2. 缓存useTable的自定义钩子配置

当前传入useTable的列注入钩子是每次渲染生成的新函数,会导致useTable认为配置变更,重新初始化内部状态,用useCallback缓存该钩子即可:

const ProductsTable = ({columns, data}) => {
  if (!data) {
    return null;
  }
  // 缓存自定义列钩子
  const injectSelectionColumn = React.useCallback((hooks) => {
    hooks.visibleColumns.push(columns => [
      {
        id: 'selection',
        Header: ({ getToggleAllPageRowsSelectedProps }) => (
          <div>
            <IndeterminateCheckbox {...getToggleAllPageRowsSelectedProps()} />
          </div>
        ),
        Cell: ({ row }) => (
          <div>
            <IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
          </div>
        ),
      },
      ...columns,
    ])
  }, [])

  const {
    // 原有导出属性保持不变
  } = useTable(
    {
      columns,
      data,
      autoResetPage: false, // 关闭数据更新时自动重置分页的默认行为
    },
    usePagination,
    useRowSelect,
    injectSelectionColumn // 传入缓存后的钩子
  )
  // 原有渲染逻辑保持不变
}

可选:受控管理分页状态

如果需要彻底避免状态丢失,可以把分页状态提到外层组件手动管理:

function Products() {
  // 新增分页状态管理
  const [pageIndex, setPageIndex] = React.useState(0)
  const [pageSize, setPageSize] = React.useState(10)
  const allProducts = useSelector(state => state.users.allProducts);
  const memorizedProducts = React.useMemo(() => allProducts, [allProducts]);
  const dispatch = useDispatch();

  useEffect(() => {
    dispatch(userActions.getAllProducts());
  }, []);

  const columns = React.useMemo(
      () => [
              {
                Header: 'Id',
                accessor: 'cell.productId',
              },
              {
                Header: 'Name',
                accessor: 'cell.name',
              }
          ],
      []
    );
  // 把分页状态传给子组件
  return (
      <ProductsTable 
        columns={columns} 
        data={memorizedProducts}
        pageIndex={pageIndex}
        pageSize={pageSize}
        onPageChange={setPageIndex}
        onPageSizeChange={setPageSize}
      />
  );
}

然后在ProductsTable的useTable配置中传入受控状态即可。

内容的提问来源于stack exchange,提问作者ivish

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 01:06:03