[英]State was mutated as a side effect?
我的代码遇到了一个奇怪的问题。 对不起,如果这已经被问到,我想搜索原因,但我什至不知道如何表述这个问题。
本质上,我有一个与此类似的代码:
class Component extends Component {
constructor(props) {
super(props);
this.state = { grid: [["", "", "", ""]], base: ["", "", "", ""]};
}
csvParse = (row, column) => e => {
const newData = Papa.parse(e.target.value).data.filter(
x => x.length !== 1 && x[0] !== ""
);
//newData will result in a 2D array such as [["1", "2", "3", "4"], ["5", "6", "7", "8"], ["9", "10", "11", "12"]]
//newData is receiving the data from a copy and paste from a CSV file
const { base } = this.state;
let grid = this.state.grid
for (let i = row; i < newData.length + row; i++) {
for (let j = column; j < 4; j++) {
try {
grid[i][j] = newData[i][j];//1
} catch (err) {
grid.push(base);//2
grid[i][j] = newData[i][j];//3 One of these is causing it, I don't know which
}
}
}
this.setState({grid},()=>{
console.log(this.state.base)
//Actually logs ["9", "10", "11", "12"] instead of ["", "", "", ""]. Why was it mutated?
})
};
render() {
//The component renders a 4 X 1 grid of textareas. The number of rows will increase based on this.state.grid. Doesn't seem like its the issue.
return (
<Fragment>
<Grid container>
{this.state.grid.map((row, rowIndex) => (
<Fragment key={rowIndex}>
<Grid item xs={3}>
<textarea
onChange={this.csvParse(rowIndex, 0)}
value={row[0]}
/>
</Grid>
<Grid item xs={3}>
<textarea
onChange={this.csvParse(rowIndex, 1)}
value={row[1]}
/>
</Grid>
<Grid item xs={3}>
<textarea
onChange={this.csvParse(rowIndex, 2)}
value={row[2]}
/>
</Grid>
<Grid item xs={3}>
<textarea
onChange={this.csvParse(rowIndex, 3)}
value={row[3]}
/>
</Grid>
</Fragment>
))}
</Grid>
</Fragment>
);
}
}
每次我运行它时 this.state.base 都会变成别的东西,比如 [""]。 如果我在没有 this.state.base 的情况下运行它,此代码没有问题
啊,我相信你希望state.base
保持['','','','']
。 如果是这种情况,请继续阅读。 否则让我知道,我们可以迭代。
要了解state.base
发生了什么变化,您需要了解按引用传递和按值传递之间的区别。
基本上在按引用传递,如果你创建一个变量a
,然后创建一个变量b
等于a
,然后更改键/值的值a
,您还可以改变b
:
var a = {'hi': 'mom'}
var b = a;
a['hi'] = 'world';
console.log(b);
// logs {hi: 'world'}
在按值传递,如果你创建一个变量a
,然后创建一个变量b
等于a
,然后更改的值a
,你都不会改变b
:
var a = true;
var b = a;
a = false;
console.log(b);
// logs true;
对象{}
和数组[]
在 JavaScript 中是按引用传递的,大多数其他原始数据类型是按值传递。 这是语言本身一个奇怪但至关重要的方面,它改变了我们编写 React 的方式。
在您的情况下,您将state.base
分配给base
,然后将base
添加到grid
,然后更改grid
。 state.base
发生变异只是时间问题。
为避免这种情况,只需更改:
grid.push(base);
到:
grid.push(Object.assign([], base));
此处的对象分配将创建一个值为base 的新变量,并将其添加到网格中。 这可以防止对grid
任何更改修改state.base
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.