javascript 如何获取:在 React 中渲染后的组件宽度

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/45996501/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 06:22:16  来源:igfitidea点击:

How to Get: Component Width After Render in React

javascriptreactjsdomreact-bootstrap

提问by R. Gulbrandsen

I'm trying to create a general purpose component, that I can reuse in other applications. I need to know the width of the component after render so that I can modify the content of the component.

我正在尝试创建一个通用组件,我可以在其他应用程序中重用它。我需要知道渲染后组件的宽度,以便我可以修改组件的内容。

I've been trying to use the different life cycles in react without success.

我一直在尝试在 react 中使用不同的生命周期,但没有成功。

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

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

When I try this I get the width of the screen, but if I change the size of the window, I get the width of the component. See the Chrome Log:

当我尝试这个时,我得到了屏幕的宽度,但是如果我改变了窗口的大小,我得到了组件的宽度。查看 Chrome 日志:

Chrome log

铬日志

ComponentDidMount executes before render so this.elementis undefined.

ComponentDidMount 在渲染之前执行,所以this.elementundefined

I've also attempted to use different libraries from npm to solve this without luck.

我也尝试使用来自 npm 的不同库来解决这个问题,但没有运气。

Futher information:The component has to work inside a Bootstrap column, at different widths.

更多信息:该组件必须在不同宽度的 Bootstrap 列中工作。

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

ClarificationI do not want to resize the window, and I apologize for not being clear. The only reason for me to mention the resizing is that when the DOM has been created and I resize, I get the correct value in offsetWidth. I'm looking for a solution where I get the correct value without resizing. Either a post render function call, listeners, some react magic, or other solutions. My problem is my lack of knowledge with the virtual vs. real DOM.

澄清我不想调整窗口大小,我为不清楚而道歉。我提到调整大小的唯一原因是,当创建 DOM 并调整大小时,我在offsetWidth. 我正在寻找一种无需调整大小即可获得正确值的解决方案。渲染后函数调用、侦听器、一些反应魔法或其他解决方案。我的问题是我对虚拟和真实 DOM 缺乏了解。

回答by R. Gulbrandsen

I was unable to solve this problem with the answers given here. I only got the width of the browser window and not the component within. After some research, it looks like I'm having a chicken or the egg problem with the render. After some more research, I found react-sizemethat solves the issue.

我无法使用此处给出的答案解决此问题。我只得到了浏览器窗口的宽度,而不是其中的组件。经过一些研究,看起来我在渲染中遇到了鸡或蛋的问题。经过更多研究,我发现react-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);

Which will produce the following when it first renders

第一次渲染时将产生以下内容

enter image description here

在此处输入图片说明

回答by Anatoly Strashkevich

If you need to hold component width state you can do something like this:

如果您需要保持组件宽度状态,您可以执行以下操作:

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
                }); 
              }
          );

};    

You can replace Observable with event listener. Alternatively you can update bounding box attached to class and derive state from it somewhere else.

您可以将 Observable 替换为事件侦听器。或者,您可以更新附加到类的边界框并在其他地方从它派生状态。

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

回答by Dimitar Christoff

Whereas this is not an answer to your question directly, it's a solution to your problem that does not add resizing and dirty logic inside of your components.

虽然这不是直接回答您的问题,但它是您的问题的解决方案,不会在组件内部添加调整大小和脏逻辑。

I'd recommend something like https://github.com/digidem/react-dimensions- which is a HOC wrapper and will listen to global resize events and send you props - containerWidthand containerHeight- I tend to use it a lot when working with SVG, canvas and data grids in react that need to remain responsive and need to know the element's size.

我会推荐类似https://github.com/digidem/react-dimensions 的东西——它是一个 HOC 包装器,会监听全局调整大小事件并向你发送道具——containerWidth而且containerHeight——我在使用 SVG 时往往会经常使用它,画布和数据网格需要保持响应并需要知道元素的大小。

As for lifecycles - things like componentDidUpdatemay not behave the way you think it should. Mount is a one-off. Read this comment - https://github.com/facebook/react/issues/2659#issuecomment-66165159

至于生命周期 - 诸如此类的事情componentDidUpdate可能不会像您认为的那样表现。Mount 是一次性的。阅读此评论 - https://github.com/facebook/react/issues/2659#issuecomment-66165159