我正在使用React渲染长的可滚动项目列表(+1000)。我发现React Virtualized可以帮助我。
所以看example here我应该将列表作为道具传递给我的项目列表组件。让我感到震惊的是,在示例中,列表是不可变的(使用Immutable.js)我认为这是有意义的,因为道具应该如何工作 - 但如果我想对行项目进行更改我不能更改其状态,因为该行将使用列表重新呈现,从而丢弃状态。
我要做的是在我点击它时突出显示一行,如果我滚出视图并再次返回该视图,它仍然会突出显示。现在,如果列表不是不可变的,我可以更改表示行的对象,突出显示的行将保持突出显示,但我不确定这是正确的方法。除了改变道具之外,还有解决方法吗?
class ItemsList extends React.Component {
(...)
render() {
(...)
return(
<div>
<VirtualScroll
ref='VirtualScroll'
className={styles.VirtualScroll}
height={virtualScrollHeight}
overscanRowCount={overscanRowCount}
noRowsRenderer={this._noRowsRenderer}
rowCount={rowCount}
rowHeight={useDynamicRowHeight ? this._getRowHeight : virtualScrollRowHeight}
rowRenderer={this._rowRenderer}
scrollToIndex={scrollToIndex}
width={300}
/>
</div>
)
}
_rowRenderer ({ index }) {
const { list } = this.props;
const row = list[index];
return (
<Row index={index} />
)
}
}
class Row extends React.Component {
constructor(props) {
super(props);
this.state = {
highlighted: false
};
}
handleClick() {
this.setState({ highlighted: true });
list[this.props.index].color = 'yellow';
}
render() {
let color = list[this.props.index].color;
return (
<div
key={this.props.index}
style={{ height: 20, backgroundColor: color }}
onClick={this.handleClick.bind(this)}
>
This is row {this.props.index}
</div>
)
}
}
const list = [array of 1000+ objects];
ReactDOM.render(
<ItemsList
list={list}
/>,
document.getElementById('app')
);
答案 0 :(得分:0)
如果你只渲染让我们一次从你的1000个列表中说出10个,那么记住highlight-flag的唯一方法就是将它存储在父状态,这是1000的列表
没有不变性,这就像是:
// make a copy of the list - NB: this will not copy objects in the list
var list = this.state.list.slice();
// so when changing object, you are directly mutating state
list[itemToChange].highlighted = true;
// setting state will trigger re-render
this.setState({ list: list });
// but the damage is already done:
// e.g. shouldComponentUpdate lifecycle method will fail
// will always return false, even if state did change.
凭借不变性,你会做一些非常相似的事情:
// make a copy of the list
var list = this.state.list.slice();
// make a copy of the object to update
var newObject = Object.assign({}, list[itemToChange]);
// update the object copy
newObject.highlighted = true;
// insert the new object into list copy
list[itemToChange] = newObject;
// update state with the new list
this.setState({ list : list );
以上仅在对象不包含更多嵌套对象时才有效 我不熟悉immutable.js,但我确信他们有更好的方法可以更恰当地处理这个问题。
反应不变性的论点是,你可以可靠而透明地处理状态变化(也就是反应的生命周期方法期望它们)。关于SO的变体有很多问题&#34;为什么nextState == this.state&#34;,答案归结为&#34;不保持状态和道具不可变的搞砸事情&#34;