【问题标题】:Using React Virtualized CellMeasurer with changing data order for List and dynamic heights使用 React Virtualized CellMeasurer 更改列表和动态高度的数据顺序
【发布时间】:2018-04-28 03:15:40
【问题描述】:

我正在尝试使用 React Virtualized 创建一个聊天应用程序。到目前为止一切正常,但我认为在使用列表中的 keyMapper 和 rowRenderer 时我做错了。

缓存使用 id 将高度存储在 _rowHeightCache 中,但似乎使用索引而不是 id 来查找高度。我不确定我是否应该将 id 作为 rowIndex 传递给 CellMeasurer 以获得正确的高度或类似的东西。

问题是由于消息列表的更改顺序导致高度错误,因此索引没有正确的高度,并且可以删除消息以弄乱索引顺序。我认为应该通过使用 keyMapper 来查找高度来解决这个问题,但我一定做错了。

以下是我如何使用它的编辑版本。

constructor(props) {
        this._cache = new CellMeasurerCache({
            defaultHeight: 45,
            fixedWidth: true,
            keyMapper: (index) => _.get(this.props.messageList[index], ['msgId'])
        });
    }

    render() {
        const props = this.filterProps(this.props),
            list = this.props.messageList,
            rowCount = list.length;

        return (

            <InfiniteLoader
                threshold={0}
                isRowLoaded={this._isRowLoaded}
                loadMoreRows={this._loadMoreRows}
                rowCount={rowCount}>
                {({onRowsRendered, registerChild}) => (
                    <AutoSizer>
                        {({width, height}) => (
                            <List
                                ref={(ref) => {
                                    this.streamLane = ref;
                                    registerChild(ref);
                                }}
                                height={height}
                                width={width}
                                onRowsRendered={onRowsRendered}
                                rowCount={rowCount}
                                rowRenderer={this._rowRenderer}
                                deferredMeasurementCache={this._cache}
                                rowHeight={this._cache.rowHeight}
                            />
                        )}
                    </AutoSizer>
                )}
            </InfiniteLoader>
       );
   }

    _rowRenderer({ index, key, parent, style }) {
        return (
            <CellMeasurer
                cache={this._cache}
                columnIndex={0}
                key={key}
                parent={parent}
                rowIndex={index}>
                <div style={{...style}}>
                    {this.props.messageList[index]}
                </div>
            </CellMeasurer>
        );
    }

    _loadMoreRows({startIndex, stopIndex}) {

        return new Promise((resolve) => {
            if (!!stopIndex || !!startIndex || this.props.hasLastMessage || this.state.isPinned) {
                return resolve();
            }

            this.props.loadOlder(() => resolve);
        });
    }

    _isRowLoaded({index}) {
        if (index === 0) return false;
        return !!this.props.messageList[index];
    }
  }

任何帮助、建议或批评都会令人惊叹。

【问题讨论】:

  • @brianvaughn 很抱歉打扰您,有人提到可能值得将您标记到此帖子。如果您没有时间,请不要担心。谢谢!

标签: react-virtualized


【解决方案1】:

问题是由于消息列表的更改顺序导致高度错误,因此索引没有正确的高度,并且可以删除消息以弄乱索引顺序。

您的示例代码没有显示订单如何更改或更改后您做了什么,因此很难说您做错了什么。

但是当顺序发生变化时(例如,您对数据进行排序,或者您将新项目添加到列表的开头导致旧项目移动),那么您需要让 List 知道它的缓存位置可能是陈旧的.在你的情况下这样做,你需要打电话给this.streamLane.recomputeRowHeights()

(您可以将第一个更改项目的索引传递给recomputeRowHeights,但我假设您的情况可能所有项目都已移动?我不知道,因为我没有您的所有代码。)

调用recomputeRowHeights 后,List 将使用CellMeasurerCache 报告给它的高度重新计算布局。 That cache uses your keyMapper function:

rowHeight = ({index}: IndexParam) => {
  const key = this._keyMapper(index, 0);

  return this._rowHeightCache.hasOwnProperty(key)
    ? this._rowHeightCache[key]
    : this._defaultHeight;
};

因此它不需要重新测量项目,即使它们的指数发生了变化。

【讨论】:

    猜你喜欢
    • 2017-04-01
    • 2018-02-09
    • 2017-04-20
    • 2021-06-20
    • 1970-01-01
    • 2020-08-11
    • 1970-01-01
    • 2019-12-22
    • 2015-12-05
    相关资源
    最近更新 更多