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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 04:06:25