动态高度的反应虚拟化无限滚动条问题

react-virtualized Infinite scroller issues with dynamic height

我正在尝试使用 react-virtualized. I am following the reference from here 在我的应用程序中像滚动条一样模拟 Facebook 提要。我试图一次加载两个提要,然后 loadMoreRows 将被调用以获取下两个提要。出于测试目的,我已将 Feed 大小硬编码为 10。它在第 4 次进食之前效果很好。然后我无法顺利移动。 rowRenderer 一次又一次地触发数字,导致屏幕出现振动效果。如果我以某种方式移动到第 10 个提要并向后滚动,rowRenderer 再次从 0 开始。我认为这是由于高度不同造成的。与参考类似,我使用 CellMeasurerCacheCellMeasurer 找到动态 heightwidth 并将其传递给列表。

class Scroller extends React.Component {
  _cache = new CellMeasurerCache({ defaultHeight: 100, fixedWidth: true });
  _resizeAllFlag = false; 
  _mostRecentWidth = 0;
  constructor(props) {
    super(props);
    this.state = {
      localCache: []
    }
  }
  componentDidMount(){
    this._loadData(0); 
  }
  componentDidUpdate(prevProps, prevState) {
    console.log(this._list);
    if(this._resizeAllFlag){
      this._resizeAllFlag = false;
      this._cache.clearAll();
      this._recomputeRowHeights();
    } else if(this.state.localCache !== prevState.localCache) {
      this._cache.clear(index, 0);
      this._recomputeRowHeights(index);
    }
  }
  ._loadData = (offset, callback) => {
    //Loads data from server and sets it in this.state.localCache
  }
  _recomputeRowHeights = (index) => {
    if (this._list) {
      console.log('Recomputing');
      this._list.recomputeRowHeights(index);
    }
  }
  _isRowLoaded = ({ index }) => {
    return !!this.state.localCache[index];
  }
  _loadMoreRows = ({ startIndex, stopIndex }) => {
    this._loadData(startIndex, (() => promiseResolver));
    let promiseResolver;
    return new Promise((resolve) => {
      promiseResolver = resolve;
    });
  }
  rowRenderer = ({ index, key, style, parent }) => {
    const row = this.state.localCache[index];
    let content;
    if (row) {
      content = (<Feed data={row}/>);
    } else {
      content = (<CustomLoader />);
    }
    return (
      <CellMeasurer
        cache={this._cache}
        columnIndex={0}
        key={key}
        parent={parent}
        rowIndex={index}
        width={this._mostRecentWidth}
      > 
        {content} 
      </CellMeasurer>);
  }
  _setListRef = (ref) => {
    this._list = ref;
    this._registerList(ref);
  };
  _resizeAll = () => {
    this._resizeAllFlag = false;
    this._cache.clearAll();
    if (this._list) {
      this._list.recomputeRowHeights();
    }
  };
  render() {
    const { localCache } = this.state;
    return (
      <div className="flex_grow">
        <InfiniteLoader
          isRowLoaded={this._isRowLoaded}
          loadMoreRows={this._loadMoreRows}
          rowCount={10}
        >
          {({ onRowsRendered, registerChild }) =>
            <AutoSizer disableHeight>
              {({ width, height }) => {
                if (this._mostRecentWidth && this._mostRecentWidth !== width) {
                  this._resizeAllFlag = true;
                  setTimeout(this._resizeAll, 0);
                }
                this._mostRecentWidth = width;
                this._registerList = registerChild;
                return (
                  <List
                    deferredMeasurementCache={this._cache}
                    overscanRowCount={1}
                    ref={this._setListRef}
                    height={height}
                    onRowsRendered={onRowsRendered}
                    rowCount={10}
                    rowHeight={this._cache.rowHeight}
                    rowRenderer={this.rowRenderer}
                    width={width}
                  />
                ) 
              }
              }
            </AutoSizer>}
        </InfiniteLoader>
      </div>
    );
  }
}

更新

我可能删除了正在传递的内容中的样式道具。根据@Adrien 的建议,我添加了它。添加样式道具后我的问题没有解决

rowRenderer = ({ index, key, style, parent }) => {
  const row = this.state.localCache[index];
  let content;
  if (row) {
    content = (<Feed style={style} data={row}/>);
  } else {
    content = (<CustomLoader style={style}/>);
  }
  return (
    <CellMeasurer
      cache={this._cache}
      columnIndex={0}
      key={key}
      parent={parent}
      rowIndex={index}
      width={this._mostRecentWidth}
    > 
      {content} 
    </CellMeasurer>);
} 

还有我的 Feed 组件

class Feed extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    const { style } = this.props;
    return (
      <div className="flex_grow" style={style}>
        {/* Feed related JSX */}
      </div>
    );
  }
}

我的组件似乎重叠了。哪里出了问题?

AnswerGist: https://gist.github.com/beb4/cc91f4e9b8982d172613cff248090769

您忘记在 content 组件中传递 rowRenderer 样式。根据 the docs,此样式对于定位您的行是强制性的。

更正了 rowRenderer

rowRenderer = ({ index, key, style, parent }) => {
    const row = this.state.localCache[index];
    let content;
    if (row) {
      content = (<Feed data={row} style={style} />); // <== HERE
    } else {
      content = (<CustomLoader style={style} />); // <== AND HERE
    }
    return (
      <CellMeasurer
        cache={this._cache}
        columnIndex={0}
        key={key}
        parent={parent}
        rowIndex={index}
        width={this._mostRecentWidth}
      > 
        {content} 
      </CellMeasurer>
    );
}