Reputation: 3
Board {
constructor(props) {
super(props);
this.state = {
array: [[{value: 12, price: 14}, {...}, {}], [{}, {}, {}], [{}, {}, {}]],
};
}
handleClick() {
let newArray = [...this.state.array];
newArray[0][0].value = 14;
this.setState({array: newArray});
}
render() {
return <Square
value={this.state.array[0][0].value}
onClick={() => this.handleClick()}
/>
}
}
function Square(props) {
return <div className="square">{props.value}</div>;
}
In the parent, I would change the state of the array with this.setState(array: newUpdatedArray) but the child component will not update even if the array state is not the same anymore. I'm new to React so I'm not quite sure when child component actually updates... after clicking on the square, the value displayed remains 12.
What I have noticed is if the child component took the whole array instead of a value, and we recovered the value from the child component, the child component would then update, but I don't want to store whole arrays in every child component.
Upvotes: 0
Views: 2993
Reputation: 268
ok it looks like what someone else mentioned before. Your data is nested array/objects. When you spread it, it only creates a shallow copy. You need to use a function to create a deep copy. You can use a library like lodash for that. Or you can create your own like this:
const deepCopy = (input) => {
if (
typeof input === 'number' ||
typeof input === 'string' ||
typeof input === 'boolean'
)
return input;
if (Array.isArray(input)) {
const newArr = [];
for (let i = 0; i < input.length; i++) {
newArr.push(deepCopy(input[i]));
}
return newArr;
} else {
const newObj = {};
for (let key in input) {
if (input.hasOwnProperty(key)) {
newObj[key] = deepCopy(input[key]);
}
}
return newObj;
}
};
Then you can have your handleClick like this:
handleClick() {
let newArray = deepCopy(this.state.array);
newArray[0][0].value = 14;
this.setState({array: newArray});
}
Upvotes: 1