Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

react get div element size incorrect

I found some relevant questions with this but none of them can't solve my problem. So, I wrote this post. If there are any relevant threads, please let me know.

I am trying to get the size (in px unit) of div element so that I can draw some SVG groups inside of it. For that, I wrote following React class after searching the web for a while.

class ChartBox extends React.Component {
     constructor() {
           super();
           this.state = {width: 0, height: 0}
     }

     componentDidMount() {
         window.addEventListener('resize', () => this.handleResize());
         this.handleResize();
     }

     componentWillUnmount() {
         window.removeEventListener('resize', () => this.handleResize());
     }

     handleResize = () => {
          this.setState({
               width: this.container.offsetWidth,
               height: this.container.offsetHeight
          });
     }

     render() {
         return (
         <div className={this.props.className}>
             <div className={theme.up}>
                  <div className={theme.left}>up.left</div>
                  <div className={theme.right}
                       ref={c => this.container = c}>
                     <p>up.right</p>
                     <p>`${this.state.width}x${this.state.height}`</p>
                  </div>
             </div>
             <div className={theme.down}>
                  <div className={theme.left}> down.left </div>                 
                  <div className={theme.right}>down.right</div>
             </div>
         </div>
         );
     }
}

The ChartBox class get a style of the outer-most div element from a parent React element. And for all inner div elements in the ChartBox class, I import following css.

:root {
   --right-width: 100px;
   --top-height: 100px;
   --left-width: calc(100% - var(--right-width));
   --bottom-height: calc(100% - var(--top-height));
}
.up {
   float: left;
   width: 100%;
   height: var(--top-height);
   padding: 0px
}
.bottom {
   float: left;
   width: 100%;
   height: var(--bottom-height);
   padding: 0px      
}
.left {
   float: left;
   width: var(--left-width);
   height: 100%;
   padding: 0px      
}
.right {
   float: left;
   width: var(--right-width);
   height: 100%;
   padding: 0px      
}

As you can imagine, I am trying to divide the outer-most div element into four sections where the smallest div element has a size of 100px by 100px.

First of all, all elements are mounted correctly when I checked it visually. However, the returned values are incorrect. For example, when I first reload the page, it returns 762 x 18 that is incorrect. But after resizing the window, it returns correct size as 100 x 100.

Any suggestions or comments to solve this issue?

like image 984
Sungsoo Ha Avatar asked Jan 31 '26 04:01

Sungsoo Ha


1 Answers

I had a similar issue. I had to use setTimeout(0) for this. For example:

 handleResize = () => {
    setTimeout(() => {
        this.setState({
           width: this.container.offsetWidth,
           height: this.container.offsetHeight
        });
    }, 0 );
 }

This ensures that the function call happens at the end of the call stack and after the container has fully rendered.

Update:

I actually found a better solution using getSnapshotBeforeUpdate. No set timeout is needed with this. From the React docs: "It enables your component to capture some information from the DOM (e.g. scroll position) before it is potentially changed."

For example:

getSnapshotBeforeUpdate() {
  let width = this.container.offsetWidth;
  let height = this.container.offsetHeight;
  return { width, height };
}

componentDidUpdate( prevProps, prevState, snapshot ) {
  if (prevState.width !== snapshot.width || prevState.height !== 
    snapshot.height) {
      this.setState({
        height: snapshot.height,
        width: snapshot.width,
      })
  }
}
like image 153
Jordan Daniels Avatar answered Feb 02 '26 18:02

Jordan Daniels