我正在阅读reactjs文档的表单部分,只是尝试了这段代码来演示onChange的用法(JSBIN)。
var React= require('react');
var ControlledForm= React.createClass({
getInitialState: function() {
return {
value: "initial value"
};
},
handleChange: function(event) {
console.log(this.state.value);
this.setState({value: event.target.value});
console.log(this.state.value);
},
render: function() {
return (
<input type="text" value={this.state.value} onChange={this.handleChange}/>
);
}
});
React.render(
<ControlledForm/>,
document.getElementById('mount')
);
当我在浏览器中更新<input/>值时,handleChange回调中的第二个console.log打印与第一个console.log相同的值,为什么我看不到这个结果。setState({value: event.target.value})在handleChange回调的范围?
正如React文档中提到的,没有保证setState被同步触发,所以你的console.log可能会在更新之前返回状态。
Michael Parker提到在setState中传递一个回调。另一种处理状态改变后逻辑的方法是通过componentDidUpdate生命周期方法,这是React文档中推荐的方法。
通常,我们建议对这种逻辑使用componentDidUpdate()。
当可能连续触发了setStates,并且您希望在每次状态更改后都触发相同的函数时,这特别有用。您可以将函数放置在componentDidUpdate中,而不是向每个setState添加回调,如果需要的话,在其中使用特定的逻辑。
// example
componentDidUpdate(prevProps, prevState) {
if (this.state.value > prevState.value) {
this.foo();
}
}
访问。由于setState方法的异步特性,在调用setState方法后,不能保证返回更新后的状态。
为了保证在调用setState之后进行更新,可以采用两种解决方案。
解决方案1:正如上述答案之一所提到的,将代码放在componentDidUpdate方法中
解决方案2:正如上面的另一个答案所提到的,将你的东西作为一个回调传递
this.setState({value: myValue}, function () {
this.functionThatIsExecutedWhenStateIsUpdated();
});
需要注意的是,这两种解决方案并不能明显互换。一个不能轻易地解决另一个的所有用例。作为一般规则,如果可以的话,最佳实践建议首选解决方案1。但是,在一些用例中,只有解决方案2“更有效”地工作,例如“更新我的视图和提交我的数据”用例。这个用例是这样的:
在添加一个项目后,说,“添加日程”,我想将该项目添加到前端列表,并立即将刚刚更新的列表发布到后端,如下面的概念所示:
如果你不做任何解决方案,也就是说,如果你只在你的代码中这样说:
addToItemArray = () => {
this.setState{{ scheduledItemsArray: newObjectListWithMax}}
this.postData();
}
<button className="btn btn-secondary btn-block" onClick={this.addToItemArray}>Add Shedule</button>
... 你将发布列表排除“Delivery to Max”项,因为当你this.postData()时状态不会更新(同样,因为它是异步的)。
如果您使用解决方案1,您将在输入日程名称文本框中的每个字符后进行POST !
还有其他方法来满足这个用例,但是解决方案2在阅读代码时最好地传达了意图。
考虑到这个用例在几乎每个web应用程序中无处不在的本质,Michael的回答中解释的回调技术是每个开发人员工具包中不可或缺的一段代码。