2017-09-01 2109 views
1

我試圖創建一個通用組件,可以在其他應用程序中重用。我需要知道渲染後組件的寬度,以便我可以修改組件的內容。如何獲取:在React渲染後的組件寬度

我一直試圖在反應中使用不同的生命週期而沒有成功。

componentDidUpdate() { 
    console.log('width', this.element.offsetWidth); 
} 

render() { 
    return (
    <div ref={(element) => {this.element = element }} /> 
); 
} 

當我嘗試這個,我得到了屏幕的寬度,但如果我改變窗口的大小,我得到的組件的寬度。看到Chrome登錄:

Chrome log

ComponentDidMount執行之前呈現這樣this.elementundefined

我也試圖用npm的不同庫來解決這個問題,但沒有運氣。

更多信息:組件必須在Bootstrap列中以不同寬度工作。

render() { 
    <Row> 
    <Col sm={3} /> 
     <MyComponent /> 
    </Col> 
    <Col sm={9} /> 
     <MyComponent /> 
    </Col> 
    <Row> 
} 

澄清我不想調整窗口的大小,我爲沒有被明確道歉。我提到調整大小的唯一原因是,當創建DOM並調整大小時,我在offsetWidth中得到正確的值。我正在尋找一種解決方案,我可以在不調整大小的情況下獲得正確的值。發佈渲染函數調用,偵聽器,一些反應魔法或其他解決方案。我的問題是我對虛擬與真實DOM缺乏瞭解。

+0

也許保存'offsetWidth'在'state',無論您何時組件改變其大小,你我若在設定狀態更新狀態 – mersocarlin

+0

annon函數setState({element:element})會產生一個無限循環。我在第一次執行時也看到該元素爲'null' –

+0

我沒有說要將該元素存儲在狀態中,而是存儲'width'值。所以每次它改變時,你都可以設置你的狀態值。 – mersocarlin

回答

1

我無法用這裏給出的答案解決此問題。我只有瀏覽器窗口的寬度,而不是內部的組件。經過一番研究後,它看起來像是在出現雞或雞蛋問題。經過一些更多的研究後,我發現可以解決問題的reat-sizeme。

import React, { Component } from 'react'; 
import sizeMe from 'react-sizeme'; 

class MyComponent extends Component { 
    render() { 
    const { width } = this.props.size; 

    return (
     <div style={{ 
     width: '100%', 
     backgroundColor: '#eee', 
     textAlign: 'center' 
     }}> 
     <span>My width is: {Math.floor(width)}px</span> 
     </div> 
    ); 
    } 
} 

export default sizeMe()(MyComponent); 

將產生以下時,第一次呈現

enter image description here

1

如果您需要持有部分寬度狀態,你可以做這樣的事情:

componentDidMount(){ 

      this.boundingBox = this.element.getBoundingClientRect(); 

      this.setState({ 
       width:this.boundingBox.width 
      }); 

      Observable.fromEvent(this.element,"resize") 
      .subscribe(
      () => { 
       this.boundingBox = this.element.getBoundingClientRect(); 
       this.setState({ 
        width:this.boundingBox.width 
       }); 
       } 
     ); 

};  

您可以替換可觀察與事件偵聽器。 或者,您可以更新附加到類的邊界框,並從其他地方派生狀態。

componentDidUpdate(){ 
      this.boundingBox = this.element.getBoundingClientRect(); 
};  
+0

'componentDidMount'在'render'之前執行,所以this.element將始終未定義。建議? –

+0

它不會,它會在渲染 –

+0

檢查文檔後執行:組件裝入後立即調用componentDidMount()。需要DOM節點的初始化應該放在這裏,DOM節點在這裏可以使用,我在發佈前測試答案 –

0

雖然這不是一個回答您的問題直接,這是你的問題的解決方案,不添加組件的內部調整和骯髒的邏輯。

我建議像https://github.com/digidem/react-dimensions - 這是一個HOC包裝,並會聽取全球的resize事件,併發送你的道具 - 用SVG,帆布和數據網格工作時,我傾向於使用了很多 - containerWidthcontainerHeight需要保持響應並需要知道元素的大小。

至於生命週期 - 像componentDidUpdate這樣的事情可能不會像你認爲的那樣行事。山是一次性的。閱讀此評論 - https://github.com/facebook/react/issues/2659#issuecomment-66165159

+0

請參閱我的問題的澄清更新。 react-dimension不能解決問題,因爲我不想調整屏幕大小來獲取組件的寬度。感謝您的鏈接,我現在對componentDidMount有了更好的理解。 –

+0

你不必調整它的大小,只要它裝上就會發送道具。 –