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

时间:2017-03-04 07:05:43

标签: javascript html reactjs event-handling

好的,我会尽快做到这一点,因为它应该是一个简单的解决方案...

我读了很多类似的问题,答案似乎很明显。从来没有什么我不得不抬头看!但是......我有一个错误,我无法理解如何解决或为什么会发生这种情况。

如下:

    $connection = mysqli_connect(your database information);

    //from the form create the main record insert statement into mysql
    mysqli_query($connection, 
    "INSERT INTO yourtable
    (fields)
    VALUES
    (values)
    ");

    //get the id of that record you just inserted
    $id = mysqli_insert_id($connection);

    // get the images from the form
    $images = $_POST['images'];
    //this is assuming your images are sent as an array of images from the form, would be slightly different if there is only one.

foreach($images as $image){
    mysqli_query($onnection,
    "INSERT INTO images_table
    (product_id, all other fields)
    VALUES
    ($id, all other values)
    "
    );
}

更多代码围绕着这个,但这就是我的问题所在。应该工作吧?

我也试过这个:

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}/>
    )
}

所以我有两个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时也是如此;如果它开始为假,那么在我第一次点击时它仍然是假的,即使复选框是否被选中是基于状态!!

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

3 个答案:

答案 0 :(得分:42)

原因是 setState是异步的,如果要检查值使用{{1},则不能指望state之后的更新setState值}} 方法。将一个方法作为回调传递,将在callback完成其任务后执行。

  

为什么setState是异步的?

这是因为setState改变了setState并导致重新渲染。这可能是一项昂贵的操作,并且使state可能会使浏览器无法响应。 因此,synchronous调用是setState以及批量处理以获得更好的UI体验和性能。

来自Doc

  

setState()不会立即改变this.state但会创建一个   待定状态转换。调用后访问this.state   方法可以返回现有值。没有   保证调用setState和调用的同步操作   为获得业绩增长而受到批评。

使用setState的回调方法:

要检查asynchronous之后的更新state值,请使用如下的回调方法:

setState

检查一下:

setState({ key: value }, () => {
     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
      }
   }

   handleOnChange = (event) => {  // Arrow function binds `this`
      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'))

答案 1 :(得分:1)

因为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 //
         });        
      }
   }

答案 2 :(得分:0)

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

相关问题