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

react-virtualized中InfiniteLoader与Masonry集成失效问题咨询

嘿,我之前在react-virtualized里结合Masonry和InfiniteLoader时也踩过一模一样的坑!这俩组件凑一起确实容易因为细节没到位导致加载回调不触发,给你梳理几个关键的排查点和修复办法:

关键排查与修复步骤

1. 务必给InfiniteLoader设置正确的rowCount

InfiniteLoader需要知道包含未加载内容的总行数才能判断何时触发加载。如果只传已加载的items长度,它会误以为所有内容都加载完了,自然不会调用loadMoreRows。

// ❌ 错误示例:仅传入已加载的数量
<InfiniteLoader
  rowCount={this.state.items.length}
  isRowLoaded={this._isRowLoaded}
  loadMoreRows={this._loadMoreRows}
>
  {/* ... */}
</InfiniteLoader>

// ✅ 正确示例:设置为已加载+预估未加载的总数(加载后更新)
<InfiniteLoader
  rowCount={this.state.totalItems} // 比如初始设为20,每次加载后加10
  isRowLoaded={this._isRowLoaded}
  loadMoreRows={this._loadMoreRows}
>
  {/* ... */}
</InfiniteLoader>

2. 确保Masonry正确传递onRowsRendered和registerChild

InfiniteLoader的子函数会返回这两个关键参数,必须准确传给Masonry:

  • registerChild用来让InfiniteLoader监听Masonry的滚动与渲染状态
  • onRowsRendered用来告知InfiniteLoader当前渲染的行范围,触发加载判断
// ✅ 正确的嵌套写法
<InfiniteLoader
  rowCount={this.state.totalItems}
  isRowLoaded={index => index < this.state.items.length}
  loadMoreRows={({ startIndex, stopIndex }) => {
    // 这里处理异步加载逻辑,记得返回Promise
    return fetchNewItems().then(newItems => {
      this.setState(prev => ({
        items: [...prev.items, ...newItems],
        totalItems: prev.totalItems + newItems.length
      }));
    });
  }}
>
  {({ onRowsRendered, registerChild }) => (
    <Masonry
      ref={registerChild}
      onRowsRendered={onRowsRendered}
      width={this.props.width}
      height={800} // 必须设置固定高度,你移除WindowScroller的操作是对的
      columnCount={2}
      rowHeight={300}
      rowRenderer={({ index, key, style }) => (
        <div key={key} style={style}>
          {this.state.items[index]}
        </div>
      )}
    />
  )}
</InfiniteLoader>

3. 检查isRowLoaded的逻辑是否正确

这个函数要返回true表示该行已加载,false表示未加载。如果逻辑写反,InfiniteLoader会认为所有行都已加载:

// ✅ 正确的判断逻辑
_isRowLoaded = index => {
  // 索引小于已加载数组长度,说明该行已加载
  return index < this.state.items.length;
};

4. 保证loadMoreRows返回Promise

InfiniteLoader依赖Promise来判断加载是否完成,如果不返回Promise,可能会出现重复触发或不触发后续加载的情况:

// ✅ 返回Promise的示例
_loadMoreRows = ({ startIndex, stopIndex }) => {
  return new Promise((resolve) => {
    // 模拟异步请求
    setTimeout(() => {
      const newItems = Array.from({ length: 10 }, (_, i) => `Item ${this.state.items.length + i}`);
      this.setState(prev => ({
        items: [...prev.items, ...newItems],
        totalItems: prev.totalItems + 10
      }), resolve); // 状态更新完成后再resolve
    }, 1000);
  });
};

如果以上几点都排查过还是不行,可以试试打印onRowsRendered的参数,看看InfiniteLoader是否接收到了正确的渲染行范围,或者检查Masonry的rowRenderer是否正确渲染了每一行。

内容的提问来源于stack exchange,提问作者João Cunha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:21:44