2017-03-04 181 views
9

好吧,我会尽量让这个快,因为它应该是一个简单的修复...为什么调用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="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相同!

但它始终返回它应该的相反。

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

这是一个疯狂的悖论,我不知道发生了什么,请帮助!

回答

19

原因是的setState是异步,你不能指望更新state值只是setState后,如果您想检查值使用callback方法。传递一个回调方法,在setState完成任务后执行回调。

为什么setState是异步的?

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

Doc

的setState()不会立即发生变异this.state而是创建一个 挂起状态转变。调用 方法后访问this.state可能会返回现有值。没有 保证同步操作对setState的调用,并且可能调用 以提高性能。

使用回调法的setState:

要刚setState后检查更新state值,使用回调方法是这样的:

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

0

这是由于性能考虑而设计的。 React中的setState是一个函数保证重新呈现组件,这是一个昂贵的CPU进程。因此,其设计人员希望通过将多个渲染操作合并为一个进行优化,因此setState是异步的。

相关问题