React JS:如何从 this.state.data 中正确删除一个项目,其中数据是一个对象数组
React JS: how to properly remove an item from this.state.data where data is an array of objects
我有一个组件可以根据通过 AJAX 调用检索到的数据数组生成包含数据行(<tr>
等)的 table。一切都适用于编辑和添加数据,但我无法确定如何制作数组的不同副本(包含对象的不同副本 - 通过 val,而不是通过 ref),以便当我删除指定的行时数据,适用的行 已从 table 中删除。
目前,因为包含的对象是引用,即使我复制了数组,我的 table 也删除了最后一行(即使行索引和数据都被正确引用和删除在我的 AJAX 通话中)。
handleRowDelete: function(rowIdx) {
// Correct row
var row = this.state.data[rowIdx];
// This makes a new array, but the contained objects are still by ref
var rows = this.state.data.slice();
// This contains the proper row that will be deleted. If this array is set to data, the table is updated to reflect just the one row - as expected.
var throwout = rows.splice(rowIdx, 1);
console.log(throwout);
// Whether I set via the React.addons:
var newState = React.addons.update(this.state, {
data: { $set: rows }
});
this.setState(newState);
// Or just set the state again via this.setState(...)
//this.setState({data: rows, add: false});
// It always just removes the last row in the component render
// Even though the proper row gets deleted following in AJAX call
$.ajax({
...
},
...
我知道 React 无法做出适当的差异,因此不会触发渲染,所以你能告诉我应该如何处理吗?
更新。相关循环:
var Grid = React.createClass({
propTypes: {
data: React.PropTypes.array.isRequired,
onCellChange: React.PropTypes.func.isRequired,
onRowCommit: React.PropTypes.func.isRequired
},
render: function() {
var rows = this.props.data.map(function(rowData, index) {
return <Row key={index} data={rowData} onCellChange={this.props.onCellChange.bind(null, index)} onRowCommit={this.props.onRowCommit.bind(null, index)} onRowDelete={this.props.onRowDelete.bind(null, index)} />;
}, this);
return (
<Table striped bordered hover responsive>
<thead>
<tr>
<th className="col-sm-4">Order Subtotal (up to)</th>
<th className="col-sm-2">Canada</th>
<th className="col-sm-2">US</th>
<th className="col-sm-2">International</th>
<th className="col-sm-1"></th>
</tr>
</thead>
<tbody>
{rows}
</tbody>
</Table>
);
}
});
您需要确保 key
值在对象实例的生命周期内保持不变。正如您所编码的,key
值基于 index
到 Array
。如果从 Array
中删除一个元素,索引会更新,键也会更新。因此,对象的 key
会发生变化,React 似乎无法正确应用新的数组更改(即使底层数组已更改)。
您需要使用每个对象实例的唯一值作为 key
或人为创建一个(只需为每个对象分配一个唯一编号)。
使用唯一键在 数据对象 中,如下所示。
data = [
{
id: 0,
contents: 'data 0',
},
{
id: 3,
contents: 'data 3',
},
{
id: 4,
contents: 'data 4',
},
];
var rows = this.props.data.map(function(rowData, index) {
return <Row key={rowData.id} data={rowData} onRowDelete={this.props.onRowDelete.bind(null, index)} />;
}, this);
React 不会重新渲染与之前有相同键的组件。
我有一个组件可以根据通过 AJAX 调用检索到的数据数组生成包含数据行(<tr>
等)的 table。一切都适用于编辑和添加数据,但我无法确定如何制作数组的不同副本(包含对象的不同副本 - 通过 val,而不是通过 ref),以便当我删除指定的行时数据,适用的行 已从 table 中删除。
目前,因为包含的对象是引用,即使我复制了数组,我的 table 也删除了最后一行(即使行索引和数据都被正确引用和删除在我的 AJAX 通话中)。
handleRowDelete: function(rowIdx) {
// Correct row
var row = this.state.data[rowIdx];
// This makes a new array, but the contained objects are still by ref
var rows = this.state.data.slice();
// This contains the proper row that will be deleted. If this array is set to data, the table is updated to reflect just the one row - as expected.
var throwout = rows.splice(rowIdx, 1);
console.log(throwout);
// Whether I set via the React.addons:
var newState = React.addons.update(this.state, {
data: { $set: rows }
});
this.setState(newState);
// Or just set the state again via this.setState(...)
//this.setState({data: rows, add: false});
// It always just removes the last row in the component render
// Even though the proper row gets deleted following in AJAX call
$.ajax({
...
},
...
我知道 React 无法做出适当的差异,因此不会触发渲染,所以你能告诉我应该如何处理吗?
更新。相关循环:
var Grid = React.createClass({
propTypes: {
data: React.PropTypes.array.isRequired,
onCellChange: React.PropTypes.func.isRequired,
onRowCommit: React.PropTypes.func.isRequired
},
render: function() {
var rows = this.props.data.map(function(rowData, index) {
return <Row key={index} data={rowData} onCellChange={this.props.onCellChange.bind(null, index)} onRowCommit={this.props.onRowCommit.bind(null, index)} onRowDelete={this.props.onRowDelete.bind(null, index)} />;
}, this);
return (
<Table striped bordered hover responsive>
<thead>
<tr>
<th className="col-sm-4">Order Subtotal (up to)</th>
<th className="col-sm-2">Canada</th>
<th className="col-sm-2">US</th>
<th className="col-sm-2">International</th>
<th className="col-sm-1"></th>
</tr>
</thead>
<tbody>
{rows}
</tbody>
</Table>
);
}
});
您需要确保 key
值在对象实例的生命周期内保持不变。正如您所编码的,key
值基于 index
到 Array
。如果从 Array
中删除一个元素,索引会更新,键也会更新。因此,对象的 key
会发生变化,React 似乎无法正确应用新的数组更改(即使底层数组已更改)。
您需要使用每个对象实例的唯一值作为 key
或人为创建一个(只需为每个对象分配一个唯一编号)。
使用唯一键在 数据对象 中,如下所示。
data = [
{
id: 0,
contents: 'data 0',
},
{
id: 3,
contents: 'data 3',
},
{
id: 4,
contents: 'data 4',
},
];
var rows = this.props.data.map(function(rowData, index) {
return <Row key={rowData.id} data={rowData} onRowDelete={this.props.onRowDelete.bind(null, index)} />;
}, this);
React 不会重新渲染与之前有相同键的组件。