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.
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:
ComponentDidMount executes before render so this.element
is undefined
.
I've also attempted to use different libraries from npm to solve this without luck.
Futher information: The component has to work inside a Bootstrap column, at different widths.
render() {
<Row>
<Col sm={3} />
<MyComponent />
</Col>
<Col sm={9} />
<MyComponent />
</Col>
<Row>
}
Clarification I 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.
To get the width of an element in a React component, we can assign a ref to the element we want to get the width of. Then we can use the offsetWidth property to get the width. to add the ref with the useRef hook. Then we pass ref as the value of the ref prop to assign the ref to the div.
To get the parent height and width in React: Set the ref prop on the element. In the useEffect hook, update the state variables for the height and width. Use the offsetHeight and offsetWidth properties to get the height and width of the element.
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-sizeme
that solves the issue.
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
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.
componentDidUpdate(){
this.boundingBox = this.element.getBoundingClientRect();
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With