React表格中InfiniteScroll仅更新一次的实现优化问询
解决React表格无限滚动仅触发一次的问题
你的代码存在几个关键问题导致无限滚动只能触发一次,以下是具体调整方案:
核心问题与修改点
- 无效的加载终止判断:原代码中
if (items.length >= items.length +1)的条件永远不成立,无法正确终止加载。需替换为判断当前加载量是否达到总数据量。 - dataLength参数错误:
dataLength应传入当前已显示的数据条数(即offset),而非全量数据的rows.length,react-infinite-scroll-component需要通过这个值判断触发下一次加载的时机。 - 状态更新的闭包陷阱:直接用
offset +10更新状态会因闭包问题导致计算错误,需改用函数式更新setOffset(prev => prev +10)。 - 缺失加载终止逻辑:当
offset超过总数据长度时,需将hasMore设为false,停止触发加载。
修改后的完整代码
import React, { useMemo, useState } from 'react'; import { useTable, useSortBy } from 'react-table'; import MOCK_DATA from '../MOCK_DATA.json'; import { Columns } from './columns'; import { Checkbox } from './Checkbox'; import InfiniteScroll from 'react-infinite-scroll-component'; export default function DefaultTable() { const columns = useMemo(() => Columns, []); const data = useMemo(() => MOCK_DATA, []); const [hasMore, setHasMore] = useState(true); const [offset, setOffset] = useState(10); const fetchMoreData = () => { // 模拟异步加载,实际场景替换为真实API请求 setTimeout(() => { const newOffset = offset + 10; // 判断是否已加载完所有数据 if (newOffset >= data.length) { setHasMore(false); } // 函数式更新避免闭包问题 setOffset(prev => prev + 10); }, 500); }; const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow, allColumns, getToggleHideAllColumnsProps } = useTable( { columns, data }, useSortBy ); return ( <div> <div> <Checkbox {...getToggleHideAllColumnsProps()} /> Toggle All {allColumns.map(column => ( <span key={column.id}> <label> <input type='checkbox' {...column.getToggleHiddenProps()} /> {column.Header} </label> </span> ))} </div> <div id="scrollableDiv" style={{ height: 320, overflow: 'auto', display: 'flex', }} > <InfiniteScroll dataLength={offset} // 改为当前已显示的数据条数 next={fetchMoreData} hasMore={hasMore} style={{ display: 'flex', flexDirection: 'column' }} loader={<h4>Loading more items...</h4>} scrollableTarget="scrollableDiv" endMessage={ <p style={{ textAlign: 'center' }}> <b>Yay! You have seen it all</b> </p> } > <table {...getTableProps()}> <thead> {headerGroups.map((headerGroup) => ( <tr {...headerGroup.getHeaderGroupProps()}> {headerGroup.headers.map((column) => ( <th {...column.getHeaderProps(column.getSortByToggleProps())}> {column.render('Header')} <span> {column.isSorted ? column.isSortedDesc ? ' 🔽' : ' 🔼' : ''} </span> </th> ))} </tr> ))} </thead> <tbody {...getTableBodyProps()}> {rows.slice(0, offset).map((row) => { prepareRow(row); return ( <tr {...row.getRowProps()}> {row.cells.map((cell) => ( <td {...cell.getCellProps()}>{cell.render('Cell')}</td> ))} </tr> ); })} </tbody> </table> </InfiniteScroll> </div> </div> ); }
额外优化说明
- 移除了未实际使用的
items状态,减少不必要的状态维护。 - 补全了排序功能的
getSortByToggleProps绑定,确保表头点击能正常触发排序。
内容的提问来源于stack exchange,提问作者Fatma Mahmoud
相关产品推荐
相关产品推荐

