为什么调用setState方法不会立即改变状态?

时间:2022-04-16 21:07:15

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!

所以我有两个console.log(),两者都应该是一样的。我确实将状态设置为与它上面的行中的event.target.checked相同!

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!!

当我使用时也是如此!this.state.barClubLounge;如果它开始为假,在我第一次点击它仍然是假的,即使复选框是否被选中是基于状态!!

It's a crazy paradox and I have no idea whats going on, please help!

这是一个疯狂的悖论,我不知道最新情况,请帮忙!

3 个解决方案

#1


27  

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.

原因是setState是异步的,你不能指望刚刚在setState之后更新状态值,如果你想检查值使用回调方法。将一个方法作为回调传递,该方法将在setState完成其任务后执行。

Why setState is asynchronous ?

为什么setState是异步的?

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.

这是因为setState改变了状态并导致重新渲染。这可能是一项昂贵的操作,并使其同步可能会使浏览器无响应。因此,setState调用既是异步的,也是批处理的,以获得更好的UI体验和性能。

From Doc:

来自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.

setState()不会立即改变this.state,但会创建挂起状态转换。调用此方法后访问this.state可能会返回现有值。无法保证对setState的调用同步操作,并且可以对调用进行批处理以提高性能。

Using callback method with setState:

使用setState的回调方法:

To check the updated state value just after the setState, use a callback method like this:

要在setState之后检查更新的状态值,请使用如下的回调方法:

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'/>

#2


0  

This is by-design due to performance considerations. setState in React is a function guaranteed to re-render Component, which is a costly CPU process. As such, its designers wanted to optimize by gathering multiple rendering actions into one, hence setState is asynchronous.

由于性能考虑,这是设计的。 React中的setState是一个保证重新呈现Component的函数,这是一个代价高昂的CPU进程。因此,其设计人员希望通过将多个渲染操作集合到一个来进行优化,因此setState是异步的。

#3


0  

Since setState is a async function. That means after calling setState state variable does not immediately change. So if you want to perform other actions immediately after changing the state you should use callback method of setstate inside your setState update function.

由于setState是异步函数。这意味着在调用setState状态变量后不会立即更改。因此,如果要在更改状态后立即执行其他操作,则应在setState更新函数中使用setstate的回调方法。

handleOnChange = (event) => { 
     let inputState = event.target.checked;
      if(event.target.className == "barClubLounge") {
         this.setState({ barClubLounge: inputState}, () => {  //here
             console.log(this.state.barClubLounge);
             //here you can call other functions which use this state 
             variable //
         });        
      }
   }

#1


27  

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.

原因是setState是异步的,你不能指望刚刚在setState之后更新状态值,如果你想检查值使用回调方法。将一个方法作为回调传递,该方法将在setState完成其任务后执行。

Why setState is asynchronous ?

为什么setState是异步的?

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.

这是因为setState改变了状态并导致重新渲染。这可能是一项昂贵的操作,并使其同步可能会使浏览器无响应。因此,setState调用既是异步的,也是批处理的,以获得更好的UI体验和性能。

From Doc:

来自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.

setState()不会立即改变this.state,但会创建挂起状态转换。调用此方法后访问this.state可能会返回现有值。无法保证对setState的调用同步操作,并且可以对调用进行批处理以提高性能。

Using callback method with setState:

使用setState的回调方法:

To check the updated state value just after the setState, use a callback method like this:

要在setState之后检查更新的状态值,请使用如下的回调方法:

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'/>

#2


0  

This is by-design due to performance considerations. setState in React is a function guaranteed to re-render Component, which is a costly CPU process. As such, its designers wanted to optimize by gathering multiple rendering actions into one, hence setState is asynchronous.

由于性能考虑,这是设计的。 React中的setState是一个保证重新呈现Component的函数,这是一个代价高昂的CPU进程。因此,其设计人员希望通过将多个渲染操作集合到一个来进行优化,因此setState是异步的。

#3


0  

Since setState is a async function. That means after calling setState state variable does not immediately change. So if you want to perform other actions immediately after changing the state you should use callback method of setstate inside your setState update function.

由于setState是异步函数。这意味着在调用setState状态变量后不会立即更改。因此,如果要在更改状态后立即执行其他操作,则应在setState更新函数中使用setstate的回调方法。

handleOnChange = (event) => { 
     let inputState = event.target.checked;
      if(event.target.className == "barClubLounge") {
         this.setState({ barClubLounge: inputState}, () => {  //here
             console.log(this.state.barClubLounge);
             //here you can call other functions which use this state 
             variable //
         });        
      }
   }