2017-09-01 2115 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

你不必调整它的大小,只要它装上就会发送道具。 –