我的React App显示一个可供选择的名称网格。当我选择一个名称时,它将读取一个数据库并显示适用于该名称的数据行。每行都是一个对象,该对象存储为单个数组元素。 我有两个包含对象的数组,一个是“原始数据”,另一个是“修改后的数据”。然后,我将它们进行比较,以查看在更新数据库之前行之一是否发生了更改。 数组的定义如下:
constructor(props) {
super(props);
this.state = {
...
detail_data: [],
old_detail_data: []
}
}
当我选择一行时,会调用_handleRowClick():
_handleRowClick(i) {
if (i >= 0) {
this.getRecord(i, (err, res) => {
if (!err) {
let detail = res.body;
this.setState({
name_detail: Object.assign({}, detail), // Stores details about the name
selectedIndex: i
})
// Fetch the Career Directions
this.fetchSingleCareerDirections(this.state.detail.animal_code); // Gets the rows
}
})
}
}
fetchSingleCareerDirections(animal_code) {
request.get(`/lookup/career_directions/${animal_code}`, (err, res) => {
let data = [].concat(res.body); // row data
this.setState({
detail_data: [...data], // array 1
old_detail_data: [...data], // array 2
});
});
}
至此一切都很好,我的数据在detail_data和old_detail_data中符合预期。因此,我在一行中修改了一条数据,在这种情况下,单击复选框(对于有效的职业),但是对行数据的任何更改都具有相同的效果:
<td>
<input type="checkbox"
checked={item.valid_career == 'Y' ? true : false}
style={{ width: 30 }}
name={"valid_career|" + i}
onChange={(e) => { this._setTableDetail("valid_career", e.target.checked == true ? 'Y' : 'N', i) }}
/>
</td>
哪个调用更新例程_setTableDetail()将'Y'或'N'存储到detail_data数组中:
_setTableDetail(name, value, index) {
let _detail_data = Object.assign([], this.state.detail_data);
_detail_data[index][name] = value;
this.setState({ detail_data: _detail_data });
}
这将按预期更新 this.state.detail_data 。但是,如果我查看 this.state.old_detail_data ,也对该数组进行了精确的更改。同样,作为测试,如果我修改更新了detail_data的old_detail_data。 之所以必须这样做,是因为两个数组都引用相同的内存空间。但是我看不到这是怎么回事。如上所示,我的setState()例程执行此操作:
this.setState({
detail_data: [...data],
old_detail_data: [...data],
});
据我所知,这使用散布运算符在每个实例中创建一个新数组。那么这两个数组都如何引用相同的内存空间?可能与我在setState()调用内进行克隆有关吗?
答案 0 :(得分:0)
非常感谢@Anthony的评论。在我出问题的地方,你说的很对。因此,尽管我的数组是唯一的,但它们包含的对象却引用了内存中的相同对象。
我修改了fetchSingleCareerDirections()函数的代码来解决此问题:
fetchSingleCareerDirections(animal_code) {
request.get(`/lookup/career_directions/${animal_code}`, (err, res) => {
let data = [].concat(res.body);
this.setState({
detail_data: data.map(row => Object.assign({}, row)), // array 1
old_detail_data: data.map(row => Object.assign({}, row)), // array 2
});
});
}
该程序现在可以正常运行了。
仅需注意一点。我正在使用JavaScript的较旧版本,但散布运算符无法正常工作(非常糟糕)。但是按照建议,事先在其他地方进行测试,我可以使用安东尼的代码,这是一种更好的现代方法:
fetchSingleCareerDirections(animal_code) {
request.get(`/lookup/career_directions/${animal_code}`, (err, res) => {
let data = [].concat(res.body);
this.setState({
detail_data: data.map(row => ({ ...row })), // spread operator
old_detail_data: data.map(row => ({ ...row })), // spread operator
});
});
}