React – How to Get Height and Width of Component Container

Calculating the size of component elements and return the height and width of containers in React using the react-sizeme library; In this react tutorial, you will learn how to get height and width on elements in a component.

A reactive application, consisting of the various components with single responsibilities can sit anywhere to do its job. In such a case, it’s very important to know how much space it needs to occupy for specific screen size.

The react-sizeme is a cool package inspired by element-resize-detector and css-element-queries to return the height and width with a highly optimised approach under the hood. It comes as a handy tool to make your awesome application, super-responsive with control on the dimensions of every component in your class.

The react-sizeme can be used by adding a compoennt wrapper or Higher Order Functions(HOF). Moreover, it provides debounce, refreshMode, monitor controls to handle its behaviour on the go.

Let’s dive into the installation steps with examples and ways to use them effectively based on your needs.

How to Calculate Height and Width of Components Dynamically in React?

Follow the step by step tutorial on adding react-sizeme and different ways to use it:

  • Step 1 – Create React App
  • Step 2 – Installation of React SizeMe package
  • Step 3 – Configuration Properties
  • Step 4 – Usage of SizeMe in React App
  • Working Demo at StackBlitz

Step 1 – Create React App

To start with, create a new react application by executing the npx command in the terminal window:

npx create-react-app react-calculate-size-app

Move into the react app directory:

cd react-calculate-size-app

Step 2 – Installation of React SizeMe package

Next, install the react-sizeme package in your application. Execute the following npm command to install the library:

npm install react-sizeme --save

Step 3 – Configuration Properties

Before using, let’s have a look at the important properties that can be passed to components or higher order functions.

  • monitorWidth (boolean, default: true) – If true, then any changes to your Components rendered width will cause a recalculation of the “size” prop which will then be be passed into your Component.
  • monitorHeight (boolean, default: false) – If true, then any changes to your Components rendered height will cause an recalculation of the “size” prop which will then be be passed into your Component.
  • refreshRate (number, default: 16) – The maximum frequency, in milliseconds, at which size changes should be recalculated when changes in your Component’s rendered size are being detected. This should not be set to lower than 16.
  • refreshMode (string, default: ‘throttle’) – The mode in which refreshing should occur. Valid values are “debounce” and “throttle”. “throttle” will eagerly measure your component and then wait for the refreshRate to pass before doing a new measurement on size changes. “debounce” will wait for a minimum of the refreshRate before it does a measurement check on your component. “debounce” can be useful in cases where your component is animated into the DOM.
  • noPlaceholder (boolean, default: false) – By default we render a “placeholder” component initially so we can try and “prefetch” the expected size for your component. This is to avoid any unnecessary deep tree renders. If you feel this is not an issue for your component case and you would like to get an eager render of your component then disable the placeholder using this config option.

Step 4 – Usage of SizeMe in React App

The implementation of SizeMe can be done as a component or higher order function. Let’s have a look at both usage with examples:

Component Usage

First, import SizeMe that can be provided with a render or children prop that will receive a size prop. The size prop is an object with width and height properties:

import React, { Component } from 'react';
import { SizeMe } from 'react-sizeme';
import MyBoxComponent from './myBoxComponent';
import MyMessageComponent from './myMessageComponent';
import './style.css';

class App extends Component {
  onSize = size => {
    console.log('MyMessageComponent has a width of', size.width);
  };

  render() {
    return (
      <div>
        <h2>Component Usage of SizeMe</h2>

        <b>Children prop</b>
        <SizeMe monitorHeight>
          {({ size }) => (
            <div className="box1 Demo">
              <div>My width is {size.width}px</div>
              <div>My height is {size.height}px</div>
            </div>
          )}
        </SizeMe>

        <b>Render prop</b>
        <SizeMe
          monitorHeight
          render={({ size }) => (
            <div className="box1 Demo">
              <div>My width is {size.width}px</div>
              <div>My height is {size.height}px</div>
            </div>
          )}
        />

        <h2>HOC Usage of SizeMe</h2>
        <MyBoxComponent />

        <h2>HOC: Get Size of Child Component</h2>
        <MyMessageComponent message="Hello world" onSize={this.onSize} />
      </div>
    );
  }
}

export default App;

The SizeMe will calculate the size of the inner element parent and update the heigh and width properties. The monitorHeight is false by default, so to return the height as well we need to add this prop.

Higher-Order Function/ Component Usage

To use it as a HOC, we need to import withSize, which is a higher-order function component provided by the SizeMe library.

import { withSize } from 'react-sizeme'

Let’s create a new file under ~src/myBoxComponent.js and update it with the following code:

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

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

    return (
      <div style={{ backgroundColor: '#5ef742' }}>
        My size is {width || -1}px x {height || -1}px
      </div>
    );
  }
}

export default withSize({ monitorHeight: true, refreshRate: 25 })(
  MyBoxComponent
);

The withSize HOF can take configuration props and component to return them with extra props of SizeMe that is size.

Get Size of Child Component in Parent Component using HOC

To demonstrate, how to get the size of a component in the parent, let’s create a new function component here ~src/myMessageComponent.js with the following code:

import React from 'react';
import { withSize } from 'react-sizeme';

function MyMessageComponent({ message }) {
  return <div style={{ backgroundColor: '#8f8fff' }}>{message}</div>;
}

export default withSize()(MyMessageComponent);

To get the above component size value in App.js(Parent), we need to define a callback prop onSize as shown below:

import React, { Component } from 'react';
import { SizeMe } from 'react-sizeme';
import MyBoxComponent from './myBoxComponent';
import MyMessageComponent from './myMessageComponent';
import './style.css';

class App extends Component {
  onSize = size => {
    console.log('MyMessageComponent has a width of', size.width);
  };

  render() {
    return (
      <div>
        <h2>Component Usage of SizeMe</h2>

        <b>Children prop</b>
        <SizeMe monitorHeight>
          {({ size }) => (
            <div className="box1 Demo">
              <div>My width is {size.width}px</div>
              <div>My height is {size.height}px</div>
            </div>
          )}
        </SizeMe>

        <b>Render prop</b>
        <SizeMe
          monitorHeight
          render={({ size }) => (
            <div className="box1 Demo">
              <div>My width is {size.width}px</div>
              <div>My height is {size.height}px</div>
            </div>
          )}
        />

        <h2>HOC Usage of SizeMe</h2>
        <MyBoxComponent />

        <h2>HOC: Get Size of Child Component in Parent</h2>
        <MyMessageComponent message="Hello world" onSize={this.onSize} />
      </div>
    );
  }
}

export default App;

The onSize function will console the size values on MyMessageComponent.

Working Demo at StackBlitz

You can see it working in the StackBlitz example below:

Leave a Reply

Your email address will not be published. Required fields are marked *