我正在尝试更新此值,但是即使条件为真,只要我console.log
总是0
。
import React, { Component } from "react";
interface orderInformation {
customer: number;
picklePrice: number;
breadPrice: number;
}
interface ComponentState {
customer: number;
picklePrice: number;
breadPrice: number;
error: string;
finalPickleCost: number;
finalBreadCost: number;
pickleCounter: number;
breadCounter: number;
}
export default class pickleSandwich extends Component<
orderInformation,
ComponentState
> {
constructor(props: orderInformation) {
super(props);
//initializing variables to undefined
this.state = {
customer: 0,
picklePrice: 0,
breadPrice: 0,
finalBreadCost: 0,
finalPickleCost: 0,
pickleCounter: 0,
breadCounter: 0,
error: ""
};
this.handleChange = this.handleChange.bind(this);
}
//Get information for the user
getInfo = orderInformation => {
orderInformation.preventDefault();
const { customer, picklePrice, breadPrice } = this.state;
console.log("customer", customer);
console.log("pickle", picklePrice);
console.log("bread", breadPrice);
if (customer > 0) {
for (var i = 0; i < customer; i++) {
if (i % 3 === 0) {
this.setState({
pickleCounter: this.state.pickleCounter + 2,
breadCounter: this.state.breadCounter + 3
});
} else {
this.setState({
pickleCounter: this.state.pickleCounter + 1,
breadCounter: this.state.breadCounter + 2
});
}
}
} else {
this.setState({
error: "Please enter amount of customer"
});
}
console.log("pickle Counter", this.state.pickleCounter);
console.log("breadCounter", this.state.breadCounter);
};
handleChange = e => {
this.setState({ [e.target.name]: e.target.value } as any);
};
render() {
// const { customer, finalPickleCost, finalBreadCost } = this.state;
return (
<form onSubmit={this.getInfo}>
<p>Get the information of the order!</p>
<input
type="text"
id="customer"
value={this.state.customer}
placeholder="Amount of Customers"
name="customer"
onChange={this.handleChange}
required
/>
<input
type="text"
id="picklePrice"
placeholder="Price of Pickle"
value={this.state.picklePrice}
name="picklePrice"
onChange={this.handleChange}
required
/>
<input
type="text"
id="breadBrice"
placeholder="Price of Bread"
value={this.state.breadPrice}
name="breadPrice"
onChange={this.handleChange}
required
/>
<button type="submit" onClick={this.getInfo}>
Get Information{" "}
</button>
</form>
);
}
}
我希望它更新值,以便我可以计算最终成本。
答案 0 :(得分:4)
反应的setState
是异步的,这意味着到您到达console.log
时,状态可能尚未更新。
有关此行为的更多信息,请参见this和this,一般请参见setState
。
要避免此问题,可以使用setState
的回调方法,该回调方法在执行状态更新后便会触发:
this.setState(prevState => ({
pickleCounter: prevState.pickleCounter + 1,
breadCounter: prevState.breadCounter + 2
}), () => {
// once you're here the state updated successfully
});
答案 1 :(得分:0)
设置状态是一个异步函数,因此,如果在同一函数中调用新状态,则通常无法访问该新状态,除非您为setState
函数使用回调:
this.setState({...content...}, callbackFunction)
编辑
使用Tobias最初提到的某项功能(如他所描述的那样无效)给了我一个主意。在这种情况下使用异步等待的一种方法是添加一个自定义函数,以使setState返回promise。
setStateAsync(state) {
return new Promise((resolve) => {
this.setState(state, resolve)
});
}
您可以使用它使函数等待状态被设置。
setStateAsync(state) {
return new Promise((resolve) => {
this.setState(state, resolve)
});
}
//Get information for the user
getInfo = async orderInformation => {
orderInformation.preventDefault();
const {
customer,
picklePrice,
breadPrice
} = this.state;
console.log("customer", customer);
console.log("pickle", picklePrice);
console.log("bread", breadPrice);
if (customer > 0) {
for (var i = 0; i < customer; i++) {
if (i % 3 === 0) {
await this.setStateAsync({
pickleCounter: this.state.pickleCounter + 2,
breadCounter: this.state.breadCounter + 3
});
} else {
await this.setStateAsync({
pickleCounter: this.state.pickleCounter + 1,
breadCounter: this.state.breadCounter + 2
});
}
}
} else {
await this.setStateAsync({
error: "Please enter amount of customer"
});
};
console.log("pickle Counter", this.state.pickleCounter);
console.log("breadCounter", this.state.breadCounter);
};
答案 2 :(得分:0)
反应setState()
可能是异步的,这意味着更新一个值然后将其合并可能会给您旧数据,这样做是错误的
// wrong, anti-pattern
this.setState({
pickleCounter: this.state.pickleCounter + 2,
breadCounter: this.state.breadCounter + 3
});
更好的方法
setState(updater [,回调])
// good
this.setState((prevState) => {
return {
pickleCounter: prevState.pickleCounter + 2,
breadCounter: prevState.breadCounter + 3
}
});
工作示例
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>
<div id="root"></div>
<script type="text/babel">
class App extends React.Component {
//initializing variables to undefined
state = {
customer: 0,
picklePrice: 0,
breadPrice: 0,
finalBreadCost: 0,
finalPickleCost: 0,
pickleCounter: 0,
breadCounter: 0,
error: ""
};
handleChange = e => {
this.setState({ [e.target.name]: e.target.value }
);
};
//Get information for the user
getInfo = async (orderInformation) => {
orderInformation.preventDefault();
const { customer, picklePrice, breadPrice } = this.state;
console.log("customer", customer);
console.log("pickle", picklePrice);
console.log("bread", breadPrice);
if (customer > 0) {
for (var i = 0; i < customer; i++) {
if (i % 3 === 0) {
await this.setState((prevState) => {
return {
pickleCounter: prevState.pickleCounter + 2,
breadCounter: prevState.breadCounter + 3
}
}, () => {
console.log("pickle Counter", this.state.pickleCounter);
console.log("breadCounter", this.state.breadCounter);
});
}
else {
await this.setState((prevState) => {
return {
pickleCounter: prevState.pickleCounter + 1,
breadCounter: prevState.breadCounter + 2
}
}, () => {
console.log("pickle Counter", this.state.pickleCounter);
console.log("breadCounter", this.state.breadCounter);
});
}
}
} else {
this.setState({
error: "Please enter amount of customer"
});
};
};
render() {
// const { customer, finalPickleCost, finalBreadCost } = this.state;
return (
<form onSubmit={this.getInfo}>
<p>Get the information of the order!</p>
<input
type="text"
id="customer"
value={this.state.customer}
placeholder="Amount of Customers"
name="customer"
onChange={this.handleChange}
required
/>
<input
type="text"
id="picklePrice"
placeholder="Price of Pickle"
value={this.state.picklePrice}
name="picklePrice"
onChange={this.handleChange}
required
/>
<input
type="text"
id="breadBrice"
placeholder="Price of Bread"
value={this.state.breadPrice}
name="breadPrice"
onChange={this.handleChange}
required
/>
<button type="submit" onClick={this.getInfo}>Get Information </button>
</form>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
</script>
您可以将回调传递给setState
,在setState完成设置状态后将调用该回调。
this.setState((prevState) => {
pickleCounter: prevState.pickleCounter + 2,
breadCounter: prevState.breadCounter + 3
}, () => {
// code here
});
或使用异步/等待
await this.setState({...})
异步/等待示例
没有异步/等待,状态可能是异步的。
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>
<div id="root"></div>
<script type="text/babel">
class App extends React.Component {
state = {
name: 'React'
};
componentDidMount = () => {
this.setState({
name: 'Peter'
});
console.log('logs old value: ', this.state.name);
}
render() {
return (
<div>
<p>{this.state.name}</p>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
</script>
使用异步/等待
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>
<div id="root"></div>
<script type="text/babel">
class App extends React.Component {
state = {
name: 'React'
};
componentDidMount = async () => {
await this.setState({
name: 'Peter'
});
console.log('logs new value: ', this.state.name);
}
render() {
return (
<div>
<p>{this.state.name}</p>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
</script>
请参阅以下文档。
答案 3 :(得分:0)
您可以更新这样的值
if(i%3 === 0)
{
this.setState((prevState)=>{
return {
pickleCounter: prevState.pickleCounter + 2,
breadCounter: prevState.breadCounter + 3
}
});
}
这里,在this.setState()
内,我们不仅提供了返回新状态的功能,而且还提供了返回旧状态的功能,而不仅仅是提供新状态。您可以为先前的状态选择任何变量名称,而不是prevState
。