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
相关产品推荐
相关产品推荐

