我在“反应虚拟化”列表中有一个交互组件,它作用于点击。单击组件时,单元格会发生变化,即高度会发生变化。
我的 rowRenderer 的第一个版本:
rowRenderer ({index, isScrolling, key, style}) {
let message = this.props.messages[index];
return <Message key={message.id} text={message.text} />
}
单击该消息时,会出现一个文本字段。这会改变高度。然而,发生的是组件在下一条消息上呈现。
发生这种情况是因为 UI 和 CellMeasurer 中的 Message 实例不同,如您所见:
<CellMeasurer
cellRenderer={
// Here we return instance 1
({ rowIndex, ...rest }) => this.rowRenderer({ index: rowIndex, ...rest })
}
columnCount={1}
rowCount={messages.length}
>
{({ getRowHeight, resetMeasurementForRow }) => {
this.resetMeasurementForRow = resetMeasurementForRow;
return <List
height={height}
overscanRowCount={50}
rowCount={messages.length}
rowHeight={getRowHeight}
rowRenderer={this.rowRenderer} // Here we create another instance
width={width}
ref={(ref)=>{
this.list = ref;
}}
/>
}}
</CellMeasurer>
List 创建的实例显然包含正确的状态,但 CellMeasurer 不知道此状态。
我测试了以下方法,但我非常怀疑这是正确的方法吗?我只是自己缓存 UI 组件实例:
rowRenderer ({index, isScrolling, key, style}) {
let message = this.props.messages[index];
if(!this.componentCache[index]) {
this.componentCache[index] = <Message key={message.id} text={message.text} />
}
return this.componentCache[index];
}
这解决了这个问题,但可能会引入许多其他问题。这样做的正确方法是什么?
(我知道使用 Flux/Redux/global state 可以解决这个问题,但我想知道这里是否缺少一些基本的反应虚拟化功能/方面。)