我有一個非常大的動態窗體,它是基於通過AJAX收集的數據呈現的。React js重新渲染大量組件
有一個包含表格的表單。該表包含一個標題,然後包含一系列行(由狀態數據確定)。每行然後有一系列單元(也由狀態數據確定)。每個單元都包含一個複選框。
我的問題是關於在哪裏維護大量複選框的狀態。最初,我的方法是使複選框控制組件,每個單元維護其複選框的狀態。
我也嘗試在父窗體組件本身上實現選擇框的狀態作爲狀態。
前一種方法的問題是,當我提交表單時,我沒有表單級別的狀態,因爲它埋在了單元格後代中。我能以某種方式得到這個狀態嗎? findDomNode
似乎只是當前組件,而不是級聯。此外,標題單元格具有複選框,只要檢查了列中的所有行,就會檢查該複選框,但此解決方案無法讓我具有更新該信息的信息。
後一種方法的問題是,當我對一個複選框進行更改時,狀態更改導致表單組件被重新呈現,這又導致整個表被重新呈現(或至少讓它的渲染方法被調用)。這是非常耗時的,對於一張大桌子(通常可能是100x50),需要非常不友好的時間來放棄。
在一天結束時,檢查複選框的影響應該非常小。複選框本身應該更新,如果列的完全選定狀態已更改,則可能需要更新列標題才能選中/取消選中。而已。
我已經剝去了很多代碼,但這基本上是我正在使用的。瞭解表格中的單元格複選框正在跟蹤應將哪些標籤應用於圖像可能會有幫助。表格標題單元跟蹤哪些標記(從圖像名稱提取的文本)被映射到哪些標記。當這種情況發生變化時,這一欄就不得不重新提出(另一個我還沒有解決的問題,如果沒有完全重新渲染一切,我懷疑它會再次變得困難)。
var AutoTagForm = React.createClass({
getInitialState: function() {
return {data: {
tags: [],
images: {},
tokens: [],
tokenTagMap: {}
}
};
},
componentDidMount: function() {
$.ajax({
url: this.props.url,
type: "POST",
data: { imageIds: this.props.images },
dataType: 'json',
cache: false,
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
onSubmit: function(e) {
e.preventDefault()
// Submit the updates to the server
},
cellCheckedChange: function(image, tag) {
// If the image has the tag, add it. Otherwise remove it
var tagIndex = image.checkedTags.indexOf(tag)
// TODO Perhaps it is safer to find the image object in this.state.data?
if (tagIndex === -1) {
image.checkedTags.push(tag);
} else {
image.checkedTags.splice(tagIndex, 1);
}
this.setState({
data: this.state.data
})
},
render: function() {
var images = this.state.data.images;
var tokenTagMap = this.state.data.tokenTagMap;
var cellCheckedChange = this.cellCheckedChange;
var rowNodes = Object.keys(images).map(function(key){
if (images.hasOwnProperty(key)) {
var image = images[key];
return (
<AutoTagImageRow key={image.id}
image={image}
tokenTagMap={tokenTagMap}
cellCheckedChange={cellCheckedChange} />
);
}
});
return (
<form ref="form" onSubmit={this.onSubmit} id="updateAllForm" className={'autotagForm'}>
<div>
<input type="submit"
value="Apply" />
</div>
<div>
<table>
<thead>
<AutoTagHeaderRow tags={this.state.data.tags}
tokens={this.state.data.tokens}
tokenTagMap={this.state.data.tokenTagMap} />
</thead>
<tbody>
{rowNodes}
</tbody>
</table>
</div>
</form>
);
}
});
var AutoTagImageRow = React.createClass({
render: function() {
var image = this.props.image;
var tokenTagMap = this.props.tokenTagMap;
var cellCheckedChange = this.props.cellCheckedChange;
var cellNodes = Object.keys(tokenTagMap).map(function(token){
if (tokenTagMap.hasOwnProperty(token)) {
return (
<AutoTagImageRowCell image={image}
token={token}
tokenTagMap={tokenTagMap}
cellCheckedChange={cellCheckedChange} />
);
}
});
return (
<tr>
{cellNodes}
<td>{image.clientPath}</td>
</tr>
);
}
});
var AutoTagImageRowCell = React.createClass({
isTagged: function() {
var image = this.props.image;
var token = this.props.token;
var tokenTagMap = this.props.tokenTagMap;
var tag = tokenTagMap[token];
return (image.tags.indexOf(tag) !== -1);
},
isChecked: function() {
var image = this.props.image;
var token = this.props.token;
var tokenTagMap = this.props.tokenTagMap;
var tag = tokenTagMap[token];
return (image.checkedTags.indexOf(tag) !== -1);
},
handleCheckedChange: function() {
var image = this.props.image;
var token = this.props.token;
var tokenTagMap = this.props.tokenTagMap;
var tag = tokenTagMap[token];
this.props.cellCheckedChange(image, tag);
},
render: function() {
var className = '';
if (this.isTagged()) {
className = 'success';
}
return (
<td className={className}>
<input type="checkbox"
checked={this.isChecked()}
onChange={this.handleCheckedChange} />
</td>
);
}
});
我是React的新手,可能會做出一些糟糕的設計決定!這與我以前通過使用簡單的JavaScript處理事情的方式截然不同,而且我很想遵循React哲學,但是我覺得它幾乎立即出錯了,因爲這是我嘗試做的第一件事通過教程。