为什么调用setState方法不立即突变状态? [英] Why calling setState method doesn't mutate the state immediately?

查看:81
本文介绍了为什么调用setState方法不立即突变状态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,我会尽快做这个,因为它应该是一个简单的修复...



我已经阅读了一堆类似的问题,而答案似乎很明显。没有什么我会永远不得不仰头在第一个地方!但是...我有一个错误,我不能理解如何解决或为什么它的发生。



如下:

  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},()=> {
console.log('updated state value',this.state.key)
})
pre>

检查:



  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 the event.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 the setState, if you want to check the value use a callback method. Pass a method as callback that will be get executed after the setState complete its task.

Why setState is asynchronous ?

This is because setState alters the state and causes re rendering. This can be an expensive operation and making it synchronous might leave the browser unresponsive. Thus the setState calls are asynchronous 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 the setState, 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆