1 | # Handle element resizes like it's 2020!
|
2 |
|
3 | <img src="https://img.shields.io/npm/dy/react-resize-detector?style=flat-square">
|
4 | <img src="https://img.shields.io/npm/dm/react-resize-detector?style=flat-square">
|
5 |
|
6 | #### [Live demo](http://maslianok.github.io/react-resize-detector/)
|
7 |
|
8 | Nowadays browsers have started to support element resize handling natively using [ResizeObservers](https://wicg.github.io/ResizeObserver/). We use this feature (with a [polyfill](https://github.com/que-etc/resize-observer-polyfill)) to help you handle element resizes in React.
|
9 | No `window.resize` listeners! No timeouts! Just a pure implementation with a lightning-fast polyfill!
|
10 |
|
11 | ## Installation
|
12 |
|
13 | ```
|
14 | npm i react-resize-detector
|
15 | // OR
|
16 | yarn add react-resize-detector
|
17 | ```
|
18 |
|
19 | ## Examples
|
20 |
|
21 | Starting from v5.0.0 there are 2 recommended ways to work with `resize-detector` library:
|
22 |
|
23 | #### 1. HOC pattern
|
24 |
|
25 | ```jsx
|
26 | import { withResizeDetector } from 'react-resize-detector';
|
27 |
|
28 | const CustomComponent = ({ width, height }) => <div>{`${width}x${height}`}</div>;
|
29 |
|
30 | export default withResizeDetector(CustomComponent);
|
31 | ```
|
32 |
|
33 | #### 2. Child Function Pattern
|
34 |
|
35 | ```jsx
|
36 | import ReactResizeDetector from 'react-resize-detector';
|
37 |
|
38 | // ...
|
39 |
|
40 | <ReactResizeDetector handleWidth handleHeight>
|
41 | {({ width, height }) => <div>{`${width}x${height}`}</div>}
|
42 | </ReactResizeDetector>;
|
43 | ```
|
44 |
|
45 | <details><summary>Full example (Class Component)</summary>
|
46 |
|
47 | ```jsx
|
48 | import React, { Component } from 'react';
|
49 | import { withResizeDetector } from 'react-resize-detector';
|
50 |
|
51 | const containerStyles = {
|
52 | height: '100vh',
|
53 | display: 'flex',
|
54 | alignItems: 'center',
|
55 | justifyContent: 'center'
|
56 | };
|
57 |
|
58 | class AdaptiveComponent extends Component {
|
59 | state = {
|
60 | color: 'red'
|
61 | };
|
62 |
|
63 | componentDidUpdate(prevProps) {
|
64 | const { width } = this.props;
|
65 |
|
66 | if (width !== prevProps.width) {
|
67 | this.setState({
|
68 | color: width > 500 ? 'coral' : 'aqua'
|
69 | });
|
70 | }
|
71 | }
|
72 |
|
73 | render() {
|
74 | const { width, height } = this.props;
|
75 | const { color } = this.state;
|
76 | return <div style={{ backgroundColor: color, ...containerStyles }}>{`${width}x${height}`}</div>;
|
77 | }
|
78 | }
|
79 |
|
80 | const AdaptiveWithDetector = withResizeDetector(AdaptiveComponent);
|
81 |
|
82 | const App = () => {
|
83 | return (
|
84 | <div>
|
85 | <p>The rectangle changes color based on its width</p>
|
86 | <AdaptiveWithDetector />
|
87 | </div>
|
88 | );
|
89 | };
|
90 |
|
91 | export default App;
|
92 | ```
|
93 |
|
94 | </details>
|
95 |
|
96 | <details><summary>Full example (Functional Component)</summary>
|
97 |
|
98 | ```jsx
|
99 | import React, { useState, useEffect } from 'react';
|
100 | import { withResizeDetector } from 'react-resize-detector';
|
101 |
|
102 | const containerStyles = {
|
103 | height: '100vh',
|
104 | display: 'flex',
|
105 | alignItems: 'center',
|
106 | justifyContent: 'center'
|
107 | };
|
108 |
|
109 | const AdaptiveComponent = ({ width, height }) => {
|
110 | const [color, setColor] = useState('red');
|
111 |
|
112 | useEffect(() => {
|
113 | setColor(width > 500 ? 'coral' : 'aqua');
|
114 | }, [width]);
|
115 |
|
116 | return <div style={{ backgroundColor: color, ...containerStyles }}>{`${width}x${height}`}</div>;
|
117 | };
|
118 |
|
119 | const AdaptiveWithDetector = withResizeDetector(AdaptiveComponent);
|
120 |
|
121 | const App = () => {
|
122 | return (
|
123 | <div>
|
124 | <p>The rectangle changes color based on its width</p>
|
125 | <AdaptiveWithDetector />
|
126 | </div>
|
127 | );
|
128 | };
|
129 |
|
130 | export default App;
|
131 | ```
|
132 |
|
133 | </details>
|
134 |
|
135 | <br/>
|
136 |
|
137 | We still support [other ways](https://github.com/maslianok/react-resize-detector/tree/v4.2.1#examples) to work with this library, but in the future consider using the ones described above. Please let me know if the examples above don't fit your needs.
|
138 |
|
139 | ## Refs
|
140 |
|
141 | The library is trying to be smart and to not add any extra DOM elements to not break your layouts. That's why we use [`findDOMNode`](https://reactjs.org/docs/react-dom.html#finddomnode) method to find and attach listeners to the existing DOM elements. Unfortunately, this method has been deprecated and throws a warning in StrictMode.
|
142 |
|
143 | For those who wants to avoid this warning we are introducing an additional property `targetRef`. You have to set this prop as a `ref` of your target DOM element and the library will use this reference instead of serching the DOM element with help of `findDOMNode`
|
144 |
|
145 | <details><summary>HOC pattern example</summary>
|
146 |
|
147 | ```jsx
|
148 | import { withResizeDetector } from 'react-resize-detector';
|
149 |
|
150 | const CustomComponent = ({ width, height, targetRef }) => <div ref={targetRef}>{`${width}x${height}`}</div>;
|
151 |
|
152 | export default withResizeDetector(CustomComponent);
|
153 | ```
|
154 |
|
155 | </details>
|
156 |
|
157 | <details><summary>Child Function Pattern example</summary>
|
158 |
|
159 | ```jsx
|
160 | import ReactResizeDetector from 'react-resize-detector';
|
161 |
|
162 | // ...
|
163 |
|
164 | <ReactResizeDetector handleWidth handleHeight>
|
165 | {({ width, height, targetRef }) => <div ref={targetRef}>{`${width}x${height}`}</div>}
|
166 | </ReactResizeDetector>;
|
167 | ```
|
168 |
|
169 | </details>
|
170 |
|
171 | ## API
|
172 |
|
173 | | Prop | Type | Description | Default |
|
174 | | -------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
|
175 | | onResize | Func | Function that will be invoked with `width` and `height` arguments | `undefined` |
|
176 | | handleWidth | Bool | Trigger `onResize` on width change | `true` |
|
177 | | handleHeight | Bool | Trigger `onResize` on height change | `true` |
|
178 | | skipOnMount | Bool | Do not trigger onResize when a component mounts | `false` |
|
179 | | refreshMode | String | Possible values: `throttle` and `debounce` See [lodash docs](https://lodash.com/docs#debounce) for more information. `undefined` - callback will be fired for every frame | `undefined` |
|
180 | | refreshRate | Number | Use this in conjunction with `refreshMode`. Important! It's a numeric prop so set it accordingly, e.g. `refreshRate={500}` | `1000` |
|
181 | | refreshOptions | Object | Use this in conjunction with `refreshMode`. An object in shape of `{ leading: bool, trailing: bool }`. Please refer to [lodash's docs](https://lodash.com/docs/4.17.11#throttle) for more info | `undefined` |
|
182 | | targetRef | Ref | Use this prop to pass a reference to the element you want to attach resize handlers to. It must be an instance of `React.useRef` or `React.createRef` functions | `undefined` |
|
183 |
|
184 | ## License
|
185 |
|
186 | MIT
|