我内部有一个交互式组件" react-virtualized"对点击起作用的列表。单击该组件时,单元格将变换,即高度发生变化。
我的第一个版本的rowRenderer:
rowRenderer ({index, isScrolling, key, style}) {
let message = this.props.messages[index];
return <Message key={message.id} text={message.text} />
}
单击该消息时,将显示一个文本字段。这会改变高度。然而,恰好是组件渲染下一条消息。
这是因为Message的实例在UI和CellMeasurer中有所不同,如您所见:
<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 /全局状态可以解决这个问题,但我想知道我在这里缺少一些基本的反应虚拟化功能/方面。)
答案 0 :(得分:2)
对此的回答实际上在文档中:
CellMeasurer的当前实现按需创建单元格, 测量它们,然后扔掉它们。这个的未来版本 组件可能会尝试克隆或以其他方式与其共享单元格 父网格以提高性能。然而,直到那 发生时,要小心使用CellMeasurer来测量有状态组件。 由于细胞是为实现测量目的而准时生成的 只能用默认状态进行测量。为了避免这个问题 现在,使用受控道具(而不是状态)进行单元格渲染 行为。
因此除了处理组件外的状态之外没有其他解决方案。在实践中,我修改如下:
rowRenderer ({index, isScrolling, key, style}) {
let message = this.props.messages[index];
let selected = message.id === store.getState().selectedMessage;
return <Message key={message.id} text={message.text} selected={selected} />
}