为多级状态对象反应 setState
React setState for multi level state object
我正在尝试更新包含多个级别的状态对象。请参阅此示例 https://codesandbox.io/s/oq9kp9vy5y。
问题是,render 方法中的值不会更新……只有第一个。我可以强制更新还是有更好的方法?
谢谢
卡斯帕
尝试这样的事情
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);
尝试:
componentDidMount() {
this.setState(
{
caclulatedUsage: {
...this.state.caclulatedUsage,
bath: 12,
kitchen: {
...this.state.caclulatedUsage.kitchen,
stove: 14,
fridge: 23,
dishwasher: 34
}
}
}
() => {
console.log(this.state);
}
);
}
在初始状态下,kitchen
对象 在 对象 calculatedUsage
中。但是在您的 setState
调用中,您有 kitchen
对象 outside of calculatedUsage
.
此外,当您访问 setState
中的先前状态时,最好使用 setState
的功能版本,例如:
componentDidMount() {
this.setState(
prevState => ({
caclulatedUsage: {
...prevState.caclulatedUsage,
bath: 12,
kitchen: {
...prevState.caclulatedUsage.kitchen,
stove: 14,
fridge: 23,
dishwasher: 34
}
}
}),
() => {
console.log(this.state);
}
);
}
原因是 setState
可以是异步的,这意味着在其中访问 this.state
可能不会给您期望的值。使用功能版本进行事务状态更改可保证一致的结果。
您可能还想看看 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
我正在尝试更新包含多个级别的状态对象。请参阅此示例 https://codesandbox.io/s/oq9kp9vy5y。
问题是,render 方法中的值不会更新……只有第一个。我可以强制更新还是有更好的方法?
谢谢 卡斯帕
尝试这样的事情
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);
尝试:
componentDidMount() {
this.setState(
{
caclulatedUsage: {
...this.state.caclulatedUsage,
bath: 12,
kitchen: {
...this.state.caclulatedUsage.kitchen,
stove: 14,
fridge: 23,
dishwasher: 34
}
}
}
() => {
console.log(this.state);
}
);
}
在初始状态下,kitchen
对象 在 对象 calculatedUsage
中。但是在您的 setState
调用中,您有 kitchen
对象 outside of calculatedUsage
.
此外,当您访问 setState
中的先前状态时,最好使用 setState
的功能版本,例如:
componentDidMount() {
this.setState(
prevState => ({
caclulatedUsage: {
...prevState.caclulatedUsage,
bath: 12,
kitchen: {
...prevState.caclulatedUsage.kitchen,
stove: 14,
fridge: 23,
dishwasher: 34
}
}
}),
() => {
console.log(this.state);
}
);
}
原因是 setState
可以是异步的,这意味着在其中访问 this.state
可能不会给您期望的值。使用功能版本进行事务状态更改可保证一致的结果。
您可能还想看看 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