为什么调用setState方法不立即突变状态? [英] Why calling setState method doesn't mutate the state immediately?
问题描述
我已经阅读了一堆类似的问题,而答案似乎很明显。没有什么我会永远不得不仰头在第一个地方!但是...我有一个错误,我不能理解如何解决或为什么它的发生。
如下:
class NightlifeTypes extends Component {
constructor(props){
super(props);
this.state = {
barClubLounge:false,
seeTheTown:true,
eventsEntertainment:true,
familyFriendlyOnly:false
}
this.handleOnChange = this.handleOnChange.bind(this);
}
handleOnChange =(event)=> {
if(event.target.className ==barClubLounge){
this.setState({barClubLounge:event.target.checked});
console.log(event.target.checked)
console.log(this.state.barClubLounge)
}
}
render(){
return(
< input className =barClubLoungetype ='checkbox'onChange = {this.handleOnChange} checked = {this.state.barClubLounge} />
)
}
更多的代码围绕着这一点,但这是我的问题所在。应该工作吗?
我也尝试过:
handleOnChange =(event )=> {
if(event.target.className ==barClubLounge){
this.setState({barClubLounge:!this.state.barClubLounge});
console.log(event.target.checked)
console.log(this.state.barClubLounge)
}
所以我有这两个 console.log()
的,都应该是一样的。我正在将状态设置为与上述行中的 event.target.checked
相同!
但它总是返回相反的。
当我使用!this.state.barClubLounge
;如果它开始错误,在我的第一次点击它仍然是虚假的,即使该复选框是否被选中是否基于状态!!
这是一个疯狂的悖论和我不知道发生了什么,请帮忙!
原因是 setState异步,你不能指望在 setState
之后的更新的状态
值,如果要检查值使用 callback
方法。将方法作为回调,在 setState
完成其任务之后将被执行。
为什么setState是异步的?
这是因为 setState
更改状态
并导致重新呈现。这可能是一个昂贵的操作,并使其同步可能会使浏览器无响应。
因此, setState
调用是异步
以及批量更好的UI体验和性能。
从 Doc
setState()不会立即变更this.state,而是创建
待处理状态过渡。调用此
方法后访问this.state可能会返回现有值。没有
保证对setState的调用同步操作,并且可以调用
来批量获取性能。
使用setState的回调方法:
要稍后检查更新的状态
setState
,使用这样的回调方法:
setState({ key:value},()=> {
pre>
console.log('updated state value',this.state.key)
})
检查:
class NightlifeTypes extends React.Component {constructor(props){super(props); this.state = {barClubLounge:false,seeTheTown:true,eventsEntertainment:true,familyFriendlyOnly:false} this.handleOnChange = this.handleOnChange.bind(this); } handleOnChange =(event)=> {let value = event.target.checked; if(event.target.className ==barClubLounge){this.setState({barClubLounge:value},()=> {//这里console.log(value); console.log(this.state.barClubLounge) ; // both will print same value}); }} render(){return(< input className =barClubLoungetype ='checkbox'onChange = {this.handleOnChange} checked = {this.state.barClubLounge} />)}} ReactDOM.render(< NightlifeTypes /> document.getElementById('app'))
< script src =https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js>< / script>< script src =https:// cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js\"></script><div id ='app'/>
Ok, i'll try and make this quick because it SHOULD be an easy fix...
I've read a bunch of similar questions, and the answer seems to be quite obvious. Nothing I would ever have to look up in the first place! But... I am having an error that I cannot fathom how to fix or why its happening.
As follows:
class NightlifeTypes extends Component { constructor(props) { super(props); this.state = { barClubLounge: false, seeTheTown: true, eventsEntertainment: true, familyFriendlyOnly: false } this.handleOnChange = this.handleOnChange.bind(this); } handleOnChange = (event) => { if(event.target.className == "barClubLounge") { this.setState({barClubLounge: event.target.checked}); console.log(event.target.checked) console.log(this.state.barClubLounge) } } render() { return ( <input className="barClubLounge" type='checkbox' onChange={this.handleOnChange} checked={this.state.barClubLounge}/> ) }
More code surrounds this but this is where my problem lies. Should work, right?
I've also tried this:
handleOnChange = (event) => { if(event.target.className == "barClubLounge") { this.setState({barClubLounge: !this.state.barClubLounge}); console.log(event.target.checked) console.log(this.state.barClubLounge) }
So I have those two
console.log()
's, both should be the same. I'm literally setting the state to be the same as theevent.target.checked
in the line above it!But it always returns the opposite of what it should.
Same goes for when I use
!this.state.barClubLounge
; If it starts false, on my first click it remains false, even though whether the checkbox is checked or not is based off of the state!!It's a crazy paradox and I have no idea whats going on, please help!
解决方案Reason is setState is asynchronous, you can't expect the updated
state
value just after thesetState
, if you want to check the value use acallback
method. Pass a method as callback that will be get executed after thesetState
complete its task.Why setState is asynchronous ?
This is because
setState
alters thestate
and causes re rendering. This can be an expensive operation and making itsynchronous
might leave the browser unresponsive. Thus thesetState
calls areasynchronous
as well as batched for better UI experience and performance.From Doc:
setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value. There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains.
Using callback method with setState:
To check the updated
state
value just after thesetState
, use a callback method like this:setState({ key: value }, () => { console.log('updated state value', this.state.key) })
Check this:
class NightlifeTypes extends React.Component { constructor(props) { super(props); this.state = { barClubLounge: false, seeTheTown: true, eventsEntertainment: true, familyFriendlyOnly: false } this.handleOnChange = this.handleOnChange.bind(this); } handleOnChange = (event) => { let value = event.target.checked; if(event.target.className == "barClubLounge") { this.setState({ barClubLounge: value}, () => { //here console.log(value); console.log(this.state.barClubLounge); //both will print same value }); } } render() { return ( <input className="barClubLounge" type='checkbox' onChange={this.handleOnChange} checked={this.state.barClubLounge}/> ) } } ReactDOM.render(<NightlifeTypes/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id='app'/>
这篇关于为什么调用setState方法不立即突变状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!