反应:状态不是实时渲染
我想建立一个网络应用程序,计算每天应该为未来旅行节省多少钱(我知道它可以很容易地通过一个简单的计算器来完成,但这是为学习的缘故)。反应:状态不是实时渲染
我的问题是,当我在两个输入中输入成本和时间时,日常储蓄计算不会实时呈现在DOM上。
这里是会发生什么:
- I型在第一输入(成本要素内)成本和留在第二输入的天数(的timeleft组件内)
- 的DOM使两者的成本而留在我键入时(在
{this.state.totalCost}
和{this.state.timeLeft}
- 的计算结果
{this.state.dailyCost}
呈现了“一个变”延迟(即成本= 100 = 10 我需要输入一些东西剩下的天实时天否则像添加一个0的成本为10在DOM中渲染为正确的结果的计算。)
谢谢你的帮助!我希望我以一种可以理解的方式解释。
我的代码:
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>
);
}
}
你onChange处理函数应该是
changeCost(newCost) {
this.setState({totalCost: Math.round(newCost)},
this.updateDailySavings);
}
changeTimeLeft(newTimeLeft) {
this.setState({timeLeft: Math.round(newTimeLeft)},
this.updateDailySavings);
}
从docs,
的setState()不总是立即更新组件。它可能会批处理或推迟更新,直到稍后。这使得在调用setState()之后立即读取this.state是一个潜在的缺陷。相反,使用componentDidUpdate或setState回调函数(setState(updater,callback)),其中的任何一个在应用更新后都会保证触发。
由于您希望在下一次setState调用中使用更新后的状态,您应该使用回调。
编辑:纠正代码删除多余()
由@bennygenel
'this.updateDailySavings()'应该是'this.updateDailySavings'。代码呈现时,您没有传递正在执行的函数。 – bennygenel
感谢您的帮助。我试过这个,但不幸的是它导致了相同的行为。 编辑:在删除()后this.updateDailySavings它完美的工作!非常感谢你palsrealm和bennygenel! – krimou32
正如指出的@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()
}
*请注意也许两个后来的setStates不再需要,但我不知道你是否使用它们后
它的工作原理!它还不完美,有时计算返回一个错误的数字(即,如果在每天输入中没有任何东西呈现0),则成本= 100,剩余时间= 1。但它是99%的功能!非常感谢:) – krimou32
对不起,我想我忘了初始化this.timeLeft和this.totalCost。你应该试试 – 2017-10-21 21:04:07
计算不呈现在重新一段时间在DOM上。
一)setState
是asynchronous,在同一个更新周期将覆盖以前的更新后续调用,并且之前的更改将丢失。
所以如果你想使用this.setState
值,你应该使用回调函数。
this.setState({value: 'value'},() => {return : /*something here ..*/});
相反变异状态(this.state.someValue
)直接的一个很好的做法,以恢复状态的一个新的副本。
return { ...previousState, value: updated new state };
你可以阅读更多Here
'setState'是异步的。如果您需要立即使用状态值,则应该使用回调。 'this.setState({some:'value'},()=> {/ * .. doSometing .. * /})' – bennygenel