I'm trying to update my state object which contains multiple levels. See this example https://codesandbox.io/s/oq9kp9vy5y.
The problem is, that the values in the render method, does not update ... only the first one. Can I force an update or is there a better way?
Thanks Kasper
In your initial state, you have the kitchen object inside the calculatedUsage object. But in your setState call, you have the kitchen object outside of calculatedUsage.
Also, when you are accessing the previous state within setState, it's best to use the functional version of setState, e.g.:
componentDidMount() {
this.setState(
prevState => ({
caclulatedUsage: {
...prevState.caclulatedUsage,
bath: 12,
kitchen: {
...prevState.caclulatedUsage.kitchen,
stove: 14,
fridge: 23,
dishwasher: 34
}
}
}),
() => {
console.log(this.state);
}
);
}
The reason for this is that setState can be asynchronous, which means that accessing this.state within it may not give you the value you expect. Using the functional version for transactional state changes guarantees consistent results.
You may also want to take a look at the immer library. It makes updating deeply nested state much easier, by allowing you to do immutable updates with a mutable API. Here's a fork of your codesandbox example that uses immer: https://codesandbox.io/s/180p7p0o84
Try something like this
import React, { Component } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends Component {
constructor(props) {
super(props);
this.state = {
caclulatedUsage: {
bath: 0,
kitchen: {
stove: 0,
fridge: 0,
dishwasher: 0
},
livingroom: {
tv: 0,
tvBox: 0
}
}
};
}
componentDidMount() {
this.setState(
{
caclulatedUsage: Object.assign({}, this.state.access, {
caclulatedUsage: {
...this.state.caclulatedUsage,
bath: 12
},
kitchen: {
...this.state.caclulatedUsage.kitchen,
stove: 14,
fridge: 23,
dishwasher: 34
}
})
},
() => {
console.log(this.state);
}
);
}
render() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
{this.state.caclulatedUsage.bath}
<br />
{this.state.caclulatedUsage.kitchen.stove}
<br />
{this.state.caclulatedUsage.kitchen.fridge}
<br />
{this.state.caclulatedUsage.kitchen.dishwasher}
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With