react-virtualized无限卷轴问题动态高度

时间:2017-08-10 10:49:58

标签: reactjs react-virtualized

我正在尝试使用react-virtualized在我的应用程序中像滚动器一样模拟Facebook Feed。我正在关注here的引用。我试图一次加载两个Feed,然后调用loadMoreRows来获取接下来的两个。为了测试目的,我已将我的Feed大小硬编码为10。它运作良好,直到第四次进料。然后我不能顺利地移动。 rowRenderer一次又一次地触发数字,这会导致屏幕上的振动效果。如果我以某种方式移动到第10个Feed并向后滚动,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

1 个答案:

答案 0 :(得分:1)

您忘记在rowRenderer组件中传递content样式。根据{{​​3}},此样式必须用于定位行。

更正了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>
    );
}