I ran into a weird problem with my code. Sorry if this is already asked, I wanted to search for the reason but I don't even know how to phrase the problem.
Essentially, I have a code similar to this:
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>
);
}
}
Every time I ran it this.state.base would change to something else, like [""]. This code has no problem if I ran it without this.state.base
Ah, I believe you want state.base
to remain ['','','','']
. If that's the case read on. Else let me know and we can iterate.
To understand what's changing state.base
you need to understand the difference between pass by reference and pass by value.
Essentially in pass by reference, if you create a variable a
, then create a variable b
equal to a
, then change the value of a key/value in a
, you'll also change b
:
var a = {'hi': 'mom'}
var b = a;
a['hi'] = 'world';
console.log(b);
// logs {hi: 'world'}
In pass by value, if you create a variable a
, then create a variable b
equal to a
, then change the value of a
, you won't change b
:
var a = true;
var b = a;
a = false;
console.log(b);
// logs true;
Objects {}
and Arrays []
are pass by reference in JavaScript, most other primitive data types are pass by value. This is a strange but critically important facet of the language itself, and it changes the way we need to write React.
In your case, you assign your state.base
to base
, then you add base
to grid
, then you mutate grid
. It's only a matter of time before state.base
gets mutated.
To avoid this, just change:
grid.push(base);
to:
grid.push(Object.assign([], base));
Object assign here will create a new variable with the value of base, and add that to grid. That prevents any changes to grid
from modifying state.base
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.