Javascript 反应:状态未实时渲染
我正在尝试建立一个网络应用程序,计算一个人每天应该为未来的旅行节省多少钱(我知道这可以很容易地用一个简单的计算器完成,但这是为了学习) 我的问题是,当我在两个输入中键入剩余的成本和时间时,每日节省量计算不会在DOM上实时呈现 发生的情况如下:Javascript 反应:状态未实时渲染,javascript,reactjs,react-redux,Javascript,Reactjs,React Redux,我正在尝试建立一个网络应用程序,计算一个人每天应该为未来的旅行节省多少钱(我知道这可以很容易地用一个简单的计算器完成,但这是为了学习) 我的问题是,当我在两个输入中键入剩余的成本和时间时,每日节省量计算不会在DOM上实时呈现 发生的情况如下: 我在第一个输入中键入成本(在成本组成部分内),在第二个输入中键入剩余天数(在时间间隔组成部分内) DOM在我键入时实时呈现成本和剩余天数(在{this.state.totalCost}和{this.state.timeLeft} 计算结果{this.sta
{this.state.totalCost}
和{this.state.timeLeft}
class App extends Component {
constructor() {
super();
this.state = {
totalCost: 0,
timeLeft: 0,
dailyCost: 0,
}
}
updateDailySavings() {
if (this.state.timeLeft !== 0) {
this.setState({dailyCost: (this.state.totalCost / this.state.timeLeft).toFixed(2)});
} else {
this.setState({dailyCost: 0});
}
}
changeCost(newCost) {
this.setState({totalCost: Math.round(newCost)});
this.updateDailySavings()
}
changeTimeLeft(newTimeLeft) {
this.setState({timeLeft: Math.round(newTimeLeft)});
this.updateDailySavings()
}
render() {
return (
<div className="App">
<header className="App-header">
<h1 className="App-title">Welcome to React</h1>
</header>
<Cost changeCost={this.changeCost.bind(this)}/>
<TimeLeft changeTimeLeft={this.changeTimeLeft.bind(this)}/> <br/>
<div>You have to save £{this.state.totalCost} in the next {this.state.timeLeft} days.<br/>
You have to save £{this.state.dailyCost} per day.
</div>
</div>
);
}
}
类应用程序扩展组件{
构造函数(){
超级();
此.state={
总成本:0,
时间限制:0,
每日成本:0,
}
}
updateDailySavings(){
if(this.state.timeLeft!==0){
this.setState({dailyCost:{this.state.totalCost/this.state.timeLeft.toFixed(2)});
}否则{
this.setState({dailyCost:0});
}
}
变更成本(新成本){
this.setState({totalCost:Math.round(newCost)});
this.updateDailySavings()
}
changeTimeLeft(newTimeLeft){
this.setState({timeLeft:Math.round(newTimeLeft)});
this.updateDailySavings()
}
render(){
返回(
欢迎反应
您必须在接下来的{this.state.timeLeft}天内保存{this.state.totalCost}。
您必须每天保存{this.state.dailyCost}。
);
}
}
您的onChange处理程序函数应该是
changeCost(newCost) {
this.setState({totalCost: Math.round(newCost)},
this.updateDailySavings);
}
changeTimeLeft(newTimeLeft) {
this.setState({timeLeft: Math.round(newTimeLeft)},
this.updateDailySavings);
}
从
setState()并不总是立即更新组件。它可能会批处理更新或将更新推迟到以后。这使得在调用setState()后立即读取This.state成为一个潜在的陷阱。相反,请使用componentDidUpdate或setState回调(setState(更新程序,回调)),其中任何一个都保证在应用更新后触发
因为您希望在下一次setState调用中使用更新的状态,所以应该使用回调
编辑:删除额外的
()
后更正了代码,正如@bennygenel所指出的那样,正如@bennygenel所指出的,setState是异步的,因此您应该执行以下操作:
updateDailySavings() {
if (this.timeLeft !== 0) {
this.setState({dailyCost: (this.totalCost / this.timeLeft).toFixed(2)});
} else {
this.setState({dailyCost: 0});
}
}
changeCost(newCost) {
this.totalCost = Math.round(newCost);
this.setState({totalCost: this.totalCost});
this.updateDailySavings()
}
changeTimeLeft(newTimeLeft) {
this.timeLeft = Math.round(newTimeLeft);
this.setState({timeLeft: this.timeLeft});
this.updateDailySavings()
}
*请注意,可能以后不再需要这两个setstate,但我不知道您是否在以后使用它们
计算不会在DOM上实时呈现
a) setState
is,同一更新周期中的后续调用将覆盖以前的更新,并且以前的更改将丢失
因此,如果要使用this.setState
值,应该使用回调函数
this.setState({value: 'value'},() => {return : /*something here ..*/});
与其直接改变状态(this.state.someValue
),不如返回状态的新副本
return { ...previousState, value: updated new state };
您可以为我阅读更多内容,我使用了async await,工作得很好
async updateDailySavings() {
if (this.state.timeLeft !== 0) {
await this.setState({dailyCost: (this.state.totalCost / this.state.timeLeft).toFixed(2)});
} else {
await this.setState({dailyCost: 0});
}
}
async changeCost(newCost) {
await this.setState({totalCost: Math.round(newCost)});
this.updateDailySavings()
}
async changeTimeLeft(newTimeLeft) {
await this.setState({timeLeft: Math.round(newTimeLeft)});
this.updateDailySavings()
}
我希望它能帮助您
设置状态
是异步的。如果需要立即使用状态值,则应该使用回调this.setState({some:'value'},()=>{/*…doSometing..*/})
this.updateDailySavings()
应该是this.updateDailySavings
。当代码呈现时,您没有传递正在执行的函数。谢谢您的帮助。我试过了,但不幸的是,结果还是一样。。编辑:删除this.updateDailySavings之后的()后,它工作得非常好!非常感谢你和bennygenel!它起作用了!它还不是完美的,有时计算返回一个错误的数字(即,在输入DailCost中没有任何内容后,如果成本=100,剩余时间=1,则呈现0)。但它99%的功能!非常感谢:)对不起,我想我忘了初始化这个.timeLeft和这个.totalCost。你应该试试