2017-03-04 117 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是異步的。

相關問題