2016-12-15 25 views
0

基本的代碼流是這樣的。componentDidUpdate()似乎在實際重新呈現發生後調用

item.js

export default class Item extends React.Component { 
    constructor(props) { 
     super(props); 

     this.state = { 
      modalIsOpen: false, 
      logs: [] 
     }; 

     this._fetchLogs = this._fetchLogs.bind(this); 
     this._fetchAnotherLogs = this._fetchAnotherLogs.bind(this); 
    } 

    render() { 
     let tableBody; 

     if (this.state.logs.length > 0) { 
      let body = []; 
      this.state.logs.forEach((log) => { 
       body.push(
        <tr key={`log${log.id}`}> 
        <td>{log.operator_name}/{log.operator_code}</td> 
        </tr> 
       ); 
      }); 

      tableBody = (
       <table className="logs"> 
       <thead> 
       <tr> 
       <th className="operator">{i18next.t('operator')}</th> 
       </tr> 
       </thead> 

       <tbody>{body}</tbody> 
       </table> 
      ); 
     } 

     return (
      <div> 
      <ul className="tabs"> 
      <li onClick={this._fetchLogs}>Logs</li> 
      <li onClick={this._fetchAnotherLogs}>Another Logs</li> 
      </ul> 

      <div className="modalContent"> 
      {tableBody} 
      </div> 
      </div> 
     ); 
    } 

    componentDidUpdate() { 
     console.log('didUpdate', $('.ReactModal__Content').height(), $(window).height()); 
    } 

    _fetchLogs() { 
     $.ajax({ 
      context: this, 
      url: URL.DEVICE_LOGS(this.props.id), 
      success(resp) { 
       const logs = resp.data; 
       this.setState({logs}); 
      }, 
      error(resp) { 
       console.log(resp); 
      }, 
     }); 
    } 

    _fetchAnotherLogs() { 
     $.ajax({ 
      context: this, 
      url: URL.DEVICE_LOGS_ANOTHER(this.props.id), 
      success(resp) { 
       const logs = resp.data; 
       this.setState({logs}); 
      }, 
      error(resp) { 
       console.log(resp); 
      }, 
     }); 
    } 
}; 

所以當點擊<li>元件時,它調用_fetchLogs(),它設置logs狀態從服務器一些陣列,和內部render(),它設置tableBody變量並填充<div className="modalContent">

我想要實現的是,通過在狀態更改後使用jQuery並且組件重新呈現表格,測量表格的高度並相應地更改一些樣式。

componentDidUpdate()註銷的是所有孩子(比如<table>)重新呈現之前的高度。

例如,如果我說的默認高度(不<table>的內容)是170像素,在後高度(與<table>內容日誌的)是340px,和後高度(與<table>內容的另一日誌)是500px,當我第一次點擊<li>它說高度是170px,但結果高度實際上是340px。如果我點擊另一個<li>來獲取另一個日誌,現在它說高度是340px,這也是錯誤的,因爲它應該是500px。

所以我認爲componentDidUpdate()只有在狀態改變後才被調用,而不是實際的重新呈現(由於狀態改變)完成。有什麼我做錯了,或者我應該考慮另一種選擇嗎?

編輯1

繼馬修·赫布斯特的答案,我認爲是合理的足夠是正確的答案,我做了一些改動,但它並沒有真正改變。

<div className="modalContent" ref={c => this._modalContent = c}> 
    {tableBody} 
</div> 

而且

componentDidUpdate() { 
    console.log('didUpdate', this._modalContent.offsetHeight); 
} 

(我也試過用jQuery來包裝它,但它並沒有改變...)

我試圖註銷渲染和componentDidUpdate()通過序列在render()return之前加上console.log()(儘管這種方式不能實現,但我知道),它清楚地表明對象日誌數組在日誌之前出現在didUpdate之前。

+0

通過觀察Chrome的React開發工具,我可以清楚地看到日誌是第一位的,而狀態更改是在日誌之後。它不應該這樣工作嗎? –

回答

0

因此,這裏發生的事情是,您實際上並沒有訪問componentDidMount中的組件,您正在訪問DOM,即使您的組件已經呈現也可能尚未更新(請記住,React必須呈現所有可能已更新的組件,然後執行單個DOM差異)。

你對使用componentDidUpdate是正確的,但你只是訪問錯誤的東西。你需要的是refs

在你render,添加ref

return (
    <div> 
    <ul className="tabs"> 
     <li onClick={this._fetchLogs}>Logs</li> 
     <li onClick={this._fetchAnotherLogs}>Another Logs</li> 
    </ul> 
    <div 
     className="modalContent" 
     ref={(myTableRef) => this.myTableRef = myTableRef} 
    > 
     {tableBody} 
    </div> 
    </div> 
); 
componentDidUpdate

然後,你可以這樣做:

componentDidUpdate() { 
    console.log('didUpdate', $(this.myTableRef).height(), $(window).height()); 
} 

這應該給你的表格模型正確的高度。

+0

正如我在編輯1中添加的那樣,它並沒有真正改變值... –

相關問題