我正在尝试使用 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];
}
}
任何帮助、建议或批评都会很棒。
问题是,由于消息列表的顺序发生变化,高度是错误的,因此索引没有正确的高度,而且消息可以被删除,从而弄乱索引顺序。
示例代码没有显示顺序如何变化或者变化后会发生什么,所以很难说出了什么问题。
但是当顺序发生变化时(例如,数据已排序或您将新项目添加到列表的开头导致旧项目移动),
List
需要“让知道”其缓存位置可能已过时。在这种情况下,应该调用 this.streamLane.recomputeRowHeights()
。
(第一个更改项目的索引可以传递给
recomputeRowHeights
,但在这种情况下,似乎所有项目都已发生变化?如果没有看到所有代码,很难说。)
调用
recomputeRowHeights
后,List
将使用 CellMeasurerCache
报告给它的高度重新计算布局。 该缓存使用您的 keyMapper
函数:
rowHeight = ({index}: IndexParam) => {
const key = this._keyMapper(index, 0);
return this._rowHeightCache.hasOwnProperty(key)
? this._rowHeightCache[key]
: this._defaultHeight;
};
因此,即使项目的指数发生了变化,也不需要重新测量。