2014-09-19 170 views
17

我有一個React類,它將通過API來獲取內容。我已確認該數據是回來了,但它不是重新渲染:React組件不會在狀態更改時重新渲染

var DealsList = React.createClass({ 
    getInitialState: function() { 
    return { deals: [] }; 
    }, 
    componentDidMount: function() { 
    this.loadDealsFromServer(); 
    }, 
    loadDealsFromServer: function() { 
    var newDeals = []; 

    chrome.runtime.sendMessage({ action: "findDeals", personId: this.props.person.id }, function(deals) { 
     newDeals = deals; 
    }); 

    this.setState({ deals: newDeals }); 
    }, 
    render: function() { 
    var dealNodes = this.state.deals.map(function(deal, index) { 
     return (
     <Deal deal={deal} key={index} /> 
    ); 
    }); 
    return (
     <div className="deals"> 
     <table> 
      <thead> 
      <tr> 
       <td>Name</td> 
       <td>Amount</td> 
       <td>Stage</td> 
       <td>Probability</td> 
       <td>Status</td> 
       <td>Exp. Close</td> 
      </tr> 
      </thead> 
      <tbody> 
      {dealNodes} 
      </tbody> 
     </table> 
     </div> 
    ); 
    } 
}); 

不過,如果我添加了一個debugger像下面,newDeals被填充,然後一旦我繼續,我看到的數據:

loadDealsFromServer: function() { 
    var newDeals = []; 

    chrome.runtime.sendMessage({ action: "findDeals", personId: this.props.person.id }, function(deals) { 
     newDeals = deals; 
    }); 
    debugger 
    this.setState({ deals: newDeals }); 
    }, 

這是什麼叫交易清單:

var Gmail = React.createClass({ 
    render: function() { 
    return (
     <div className="main"> 
     <div className="panel"> 
      <DealsList person={this.props.person} /> 
     </div> 
     </div> 
    ); 
    } 
}); 

回答

8

這是因爲從chrome.runtime.sendMessage響應是異步的;這裏是操作順序:

​​

當你用調試器暫停腳本時,你給了擴展時間來調用回調;當你繼續時,數據已經到達,它似乎工作。

要解決,你想要做的setState通話將數據從Chrome擴展回來後:

var newDeals = []; 

// (1) first chrome.runtime.sendMessage is called, and *registers a callback* 
// so that when the data comes back *in the future* 
// the function will be called 
chrome.runtime.sendMessage({...}, function(deals) { 
    // (2) sometime in the future, this function runs 
    newDeals = deals; 

    // (3) now you can call `setState` with the data 
    this.setState({ deals: newDeals }); 
}.bind(this)); 
+0

呃!當調試器線修復它時,我應該知道這種情況。當我第一次嘗試這個時,綁定(這個)是我錯過的東西。謝謝,非常詳細的評論! – brandonhilkert 2014-09-19 15:54:37

32

我想添加到這個的極大簡單,但是是如此容易犯的錯誤寫作:

this.state.something = 'changed'; 

...然後不明白爲什麼它不渲染和谷歌搜索,並在此頁的到來,只有認識到,你應該寫:

this.setState({something: 'changed'}); 

如果您使用setState更新狀態,則React僅觸發重新呈現。

+0

這是我遇到的確切問題。奇怪的是,他們沒有發出警告,因爲他們在嘗試更新道具時會拋出一個警告。 – AndrewJM 2015-12-13 22:38:37

+0

謝謝好先生 – heinst 2016-05-02 14:04:40

+0

@AndrewJM他們不能發出警告。他們可以,如果你寫'this.state ='something'',因爲你會碰到'state'的setter,但是在上面的例子中,代碼碰到了getter,它返回一個對象,然後結束設置一個對象上的字段只是狀態的一個副本。 – 2017-06-23 21:37:07

6

另一個非常容易的錯誤,這是我的問題的根源:我寫了自己的shouldComponentUpdate方法,它沒有檢查我添加的新狀態更改。

相關問題