What is react-sizeme?
The react-sizeme package is a React higher-order component (HOC) that makes it easy to get the dimensions of a component. It provides a way to measure the size of a component and pass those dimensions as props to the component, enabling responsive design and dynamic rendering based on component size.
What are react-sizeme's main functionalities?
Basic Usage
This example demonstrates the basic usage of react-sizeme. The SizeMe HOC is used to wrap a component, and it injects the size (width and height) as props into the wrapped component.
```jsx
import React from 'react';
import { SizeMe } from 'react-sizeme';
const MyComponent = ({ size }) => (
<div>
{`Width: ${size.width}, Height: ${size.height}`}
</div>
);
const SizeAwareComponent = SizeMe({ monitorHeight: true })(MyComponent);
export default SizeAwareComponent;
```
Using with Functional Components
This example shows how to use react-sizeme with functional components. The SizeMe HOC wraps the functional component and provides the size as props.
```jsx
import React from 'react';
import { SizeMe } from 'react-sizeme';
const MyFunctionalComponent = ({ size }) => (
<div>
{`Width: ${size.width}, Height: ${size.height}`}
</div>
);
const SizeAwareFunctionalComponent = SizeMe({ monitorHeight: true })(MyFunctionalComponent);
export default SizeAwareFunctionalComponent;
```
Custom Configuration
This example demonstrates how to use custom configuration options with react-sizeme. The options include monitoring width and height, setting a refresh rate, and disabling the placeholder.
```jsx
import React from 'react';
import { SizeMe } from 'react-sizeme';
const MyComponent = ({ size }) => (
<div>
{`Width: ${size.width}, Height: ${size.height}`}
</div>
);
const SizeAwareComponent = SizeMe({
monitorWidth: true,
monitorHeight: true,
refreshRate: 100,
noPlaceholder: true
})(MyComponent);
export default SizeAwareComponent;
```
Other packages similar to react-sizeme
react-measure
react-measure is a package that provides a higher-order component and a render prop component to measure the size of a component. It offers more flexibility with render props and supports more detailed measurements like margins and padding. Compared to react-sizeme, react-measure provides more granular control over what measurements are taken and how they are used.
react-resize-detector
react-resize-detector is a lightweight package that provides a higher-order component and a hook to detect resize events on a component. It is simpler and more focused on detecting resize events rather than providing detailed size measurements. Compared to react-sizeme, react-resize-detector is more lightweight and easier to use for simple resize detection.
react-use-measure
react-use-measure is a hook-based package that provides a way to measure the size of a component using the ResizeObserver API. It is modern and hook-based, making it a good fit for functional components and hooks-based codebases. Compared to react-sizeme, react-use-measure is more modern and leverages the latest React features.
Make your React Components aware of their width and height
- Easy to use.
- Extensive browser support.
- Supports any Component type, i.e. stateless/class.
- Works with React 0.14.x and 15.x.x.
- 7.67KB gzipped
- Responsive Components!
What is this for?
Give your Components the ability to have render logic based on their height/width.
Live Demo
Perhaps it's easiest just to show a live example:
https://react-sizeme-example-esbefmsitg.now.sh
Simple Example
Below is a partial example highlighting the use of the library. Read the Usage section in it's entirety for a full description on configuration and usage.
class MyComponent extends Component {
render() {
const { width, height } = this.props.size;
return (
<div>My size is {width}px x {height}px</div>
);
}
}
export default SizeMeHOC(MyComponent); // Wired up here!
Usage
First install the library.
npm install react-sizeme
Then identify a Component you would like to make aware of it's size. We provide you with a helper function called SizeMe
. You can import it like so:
import SizeMe from 'react-sizeme';
You first have to pass the SizeMe
function a configuration object. The entire configuration object is optional, as is each of it's properties, in which case the defaults would be used. Here is a full configuration example with the default values for each of the properties:
const SizeMeHOC = SizeMe({
// If true any changes to `width` will result in a new `size` prop being
// passed to your Component.
monitorWidth: true,
// If true any changes to `height` will result in a new `size` prop being
// passed to your Component.
monitorHeight: false,
// The maximum speed, in milliseconds, at which size changes should be
// propogated to your Components. This should not be set to lower than 16.
refreshRate: 16
});
When you execute the SizeMe
function it will return a Higher Order Component. You can use this Higher Order Component to decorate any of your existing Components with the size awareness ability. Each of the Components you decorate will then recieve a size
prop, which is an object of schema { width: number, height: number }
- the numbers representing pixel values. Below is an example:
class MyComponent extends Component {
render() {
const { width, height } = this.props.size;
return (
<div>My size is {width}px x {height}px</div>
);
}
}
export default SizeMeHOC(MyComponent); // Wired up here!
That's it. It's really useful for doing things like optionally loading a child component based on the available space.
Here is an full example of that in action:
import React, { PropTypes } from 'react';
import LargeChildComponent from './LargeChildComponent';
import SmallChildComponent from './SmallChildComponent';
import SizeMe from 'react-sizeme';
function MyComponent(props) {
const { width, height } = props.size;
const ToRenderChild = height > 600
? LargeChildComponent
: SmallChildComponent;
return (
<div>
<h1>My size is {width}x{height}</div>
<ToRenderChild />
</div>
);
}
MyComponent.propTypes = {
size: PropTypes.shape({
width: PropTypes.number.isRequired,
height: PropTypes.number.isRequired,
})
}
export default SizeMe({ monitorHeight: true })(MyComponent);
On the First Render of your Component
Ok, we have a bit of a chicken/egg scenario. We can't know the width/height of your Component until it is rendered. This can lead to less than ideal cases, for example based on the rendered size of your component you may have logic that renders the internals of your component entirely. This can lead to some wasteful rendering.
Therefore for the first render of your component we actually render a lightweight placeholder in order to obtain the width/height for your Component render. In addition to this, if you were passing any className
or style
props into your object these will be used for the render of the placeholder, which can be useful in cases where you are pre-rendering it with specific dimensions based on the CSS.
An example of this:
import cssStyles from './styles.css';
import MySizeAwareComponent from './MySizeAwareComponent';
const inlineStyle = {
backgroundColor: 'pink'
};
function App() {
return (
<MySizeAwareComponent
className={cssStyles.foo}
style={inlineStyle} />
);
}
In cases where the styles/classes are contained within your component and you want more accurate first-render size
resolving we recommend that you create a wrapper component that passes the className/style into your component. For example we could refactor our MySizeAwareComponent
like so:
import React from 'react';
import cssStyles from './styles.css';
import SizeMe from 'react-sizeme';
class MyComponent extends Component {
render() {
const className = this.props.className;
const { width, height } = this.props.size;
return (
<div className={className}>
My size is {width}px x {height}px
</div>
);
}
}
const MySizeAwareComponent = SizeMeHOC(MyComponent);
// We create this wrapper component so that our size aware rendering
// will have a handle on the rendered components css classname.
function MyComponentWrapper(props) {
return (
<MySizeAwareComponent className={cssStyles.foo} {...props} />
);
}
export default MyComponentWrapper;
Under the Hood
We make use of the awesome element-resize-detector library. This library makes use of an scroll/object based event strategy which outperforms window resize event listening dramatically. The original idea from this approach comes from another library, namely css-element-queries by Marc J. Schmidt. I recommend looking into these libraries for history, specifics, and more examples.
Caveats.
- Server Side Rendering is not supported. I am still thinking of the best approach on what to do in the case of a SSR request. Perhaps I will just return null values for width/height. Undecided. Any recommendations are welcome.
- Whilst execution is performant and we try and do smart rendering mechanisms we don't recommend that you place a crazy amount of size aware components into your render tree. If you do require this I highly recommend you do some decent browser testing for impact.