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
答案 0 :(得分:2)
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
答案 1 :(得分:1)
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);
答案 2 :(得分:0)
Try:
componentDidMount() {
this.setState(
{
caclulatedUsage: {
...this.state.caclulatedUsage,
bath: 12,
kitchen: {
...this.state.caclulatedUsage.kitchen,
stove: 14,
fridge: 23,
dishwasher: 34
}
}
}
() => {
console.log(this.state);
}
);
}