我有一个非常大的动态窗体,它是基于通过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哲学,但是我觉得它几乎立即出错了,因为这是我尝试做的第一件事通过教程。