我无法弄清楚如何短路渲染分支 使用Immutable.js游标的React组件树。
采用以下示例:
import React from 'react';
import Immutable from 'immutable';
import Cursor from 'immutable/contrib/cursor';
let data = Immutable.fromJS({
things: [
{title: '', key: 1},
{title: '', key: 2}
]
});
class Thing extends React.Component {
shouldComponentUpdate(nextProps) {
return this.props.thing.deref() !== nextProps.thing.deref();
}
handleChangeTitle(e) {
this.props.thing.set('title', e.target.value);
}
render() {
return <div>
<input value={this.props.thing.get('title')}
onChange={this.handleChangeTitle.bind(this)} />
</div>;
}
}
class Container extends React.Component {
render() {
const cursor = Cursor.from(this.props.data, 'things', newThings => {
data.set('things', newThings);
renderContainer();
});
const things = cursor.map(thing => (
<Thing thing={thing} key={thing.get('key')} />
));
return <div>
{things}
</div>;
}
}
const renderContainer = () => {
React.render(<Container data={data} />, document.getElementById('someDiv'));
};
说我改变了第一个Thing
的标题。只有第一个Thing
会呈现
新标题和第二个Thing
将不会重新呈现
shouldComponentUpdate
。但是,如果我更改了第二个Thing
的标题,那么
自第二个Thing
游标以来,第一个''
的标题将返回Thing
仍然指向较旧版本的根数据。
我们会更新每个Container
渲染上的游标,但不会更新游标
由shouldComponentUpdate
引起的渲染也不会获得更新后的新光标
根数据。我可以看到保持游标最新的唯一方法是删除
此示例中shouldComponentUpdate
组件中的Thing
。
是否有办法更改此示例以使用快速参照使用shouldComponentUpdate
平等检查,但也保持游标更新?
或者,如果不可能,您是否可以概述一下如何使用游标+ React组件并仅渲染具有更新数据的组件?
答案 0 :(得分:1)
我更新了您的代码,请参阅内联评论:
class Thing extends React.Component {
shouldComponentUpdate(nextProps) {
return this.props.thing.deref() !== nextProps.thing.deref();
}
handleChangeTitle(e) {
// trigger method on Container to handle update
this.props.onTitleChange(this.props.thing.get('key'), e.target.value);
}
render() {
return <div>
<input value={this.props.thing.get('title')}
onChange={this.handleChangeTitle.bind(this)} />
</div>;
}
}
class Container extends React.Component {
constructor() {
super();
this.initCursor();
}
initCursor() {
// store cursor as instance variable to get access from methods
this.cursor = Cursor.from(data, 'things', newThings => {
data = data.set('things', newThings);
// trigger re-render
this.forceUpdate();
});
}
render() {
const things = this.cursor.map(thing => (
<Thing thing={thing} key={thing.get('key')} onTitleChange={this.onTitleChange.bind(this)} />
));
return <div>
{things}
</div>;
}
onTitleChange(key, title){
// update cursor to store changed things
this.cursor = this.cursor.update(x => {
// update single thing
var thing = x.get(key - 1).set('title', title);
// return updated things
return x.set(key - 1,thing);
});
}
}
const renderContainer = () => {
React.render(<Container data={data} />, document.getElementById('someDiv'));
};