【问题标题】:react-virtualized Infinite scroller issues with dynamic height具有动态高度的反应虚拟化无限滚动问题
【发布时间】:2018-01-18 13:57:08
【问题描述】:

我正在尝试使用 react-virtualized 在我的应用程序中模拟 Facebook 提要,如滚动条。我正在关注here 的参考。我正在尝试一次加载两个提要,然后将调用 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>
    );
  }
}

我的组件似乎重叠。可能出了什么问题?

答疑者https://gist.github.com/beb4/cc91f4e9b8982d172613cff248090769

【问题讨论】:

    标签: reactjs react-virtualized


    【解决方案1】:

    您忘记在 content 组件中传递 rowRenderer 样式。根据the docs 的说法,这种样式是强制定位行的。

    更正行渲染器

    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>
        );
    }
    

    【讨论】:

    • 感谢您的帮助。我最初有风格。不知何故,在编辑时我可能已经删除了它。我按照你的建议再次添加。即使添加了style props,我也遇到了同样的问题。
    • @user2193672 你是否在Feed 组件内的根节点上应用style 属性?你能粘贴你的代码吗?
    • 是的。我将 style 道具传递给了我的 FeedCustomLoader ,而不是按照您的建议传递给 CellMeasurer 。已经用它更新了问题。
    • @user2193672 我的意思是应用style 不仅仅是传递style 属性,而是在Feed 组件中处理它。你能粘贴你的Feed 组件吗? (仅渲染)
    猜你喜欢
    • 2018-01-03
    • 2019-06-12
    • 2017-08-20
    • 1970-01-01
    • 2017-10-05
    • 2018-04-28
    • 2018-05-09
    • 1970-01-01
    • 2020-11-10
    相关资源
    最近更新 更多