|
1 | 1 | # react-resize-aware
|
2 | 2 |
|
3 |
| -A simple React.js component you can use to make any piece of UI aware of its size. |
| 3 | +It does one thing, it does it well: listens to resize events on any HTML element. |
4 | 4 |
|
5 |
| -Each time the component' size changes, your component will be notified by one of |
6 |
| -the methods described below. |
7 |
| -The size change can be detected by a window resize, a CSS media query, |
8 |
| -a CSS pseudo selector, a JavaScript action or really, anything. |
| 5 | +`react-resize-aware` is a zero dependency, **~400 bytes** [React Hook](https://reactjs.org/docs/hooks-reference.html) you can use to detect resize events without relying on intervals, loops, DOM manipulation detection or CSS redraws. |
9 | 6 |
|
10 |
| -**This component doesn't rely on intervals, loops, DOM manipulation detection |
11 |
| -or any other weird stuff. |
12 |
| -It takes advantage of the `resize` event of the `<object>` HTML element.** |
| 7 | +**It takes advantage of the `resize` event on the `HTMLObjectElement`, works on any browser I know of, and it's super lightweight.** |
13 | 8 |
|
14 |
| -You don't have to care about anything, it will always work as you expect in any |
15 |
| -possible scenario. |
16 |
| -Also, it's just 2.6KB (or 1.2KB gzipped)! (no dependencies!) |
17 |
| - |
18 |
| -Install it with: |
| 9 | +## Installation |
19 | 10 |
|
20 | 11 | ```
|
21 | 12 | yarn add react-resize-aware
|
22 |
| -# or |
23 |
| -npm install --save react-resize-aware |
24 | 13 | ```
|
25 | 14 |
|
26 |
| -# Usage |
27 |
| - |
28 |
| -> **note**: `ResizeAware` needs a position different from `initial` to work! |
29 |
| -> Make sure to set it to `relative`, `absolute` or `fixed` using its `style` property or with CSS |
30 |
| -
|
31 |
| -## Stateless approach |
32 |
| - |
33 |
| -If your component is stateless or you prefer to follow a functional approach |
34 |
| -you can use ResizeAware to wrap your existing component and it will take care |
35 |
| -to provide two property (`height` and `width`) that will get updated every time |
36 |
| -the component sizes change. |
| 15 | +or with npm: |
37 | 16 |
|
38 |
| -```jsx |
39 |
| -import React from 'react'; |
40 |
| -import ResizeAware from 'react-resize-aware'; |
41 |
| - |
42 |
| -// This component will get re-rendered every time its width or height changes |
43 |
| -function MyComponent({width, height}) { |
44 |
| - return <div>{width}x{height}</div>; |
45 |
| -} |
46 |
| - |
47 |
| -function App() { |
48 |
| - return ( |
49 |
| - <ResizeAware style={{ position: 'relative' }}> |
50 |
| - <MyComponent /> |
51 |
| - </ResizeAware> |
52 |
| - ); |
53 |
| -} |
54 | 17 | ```
|
55 |
| - |
56 |
| -## Stateful approach |
57 |
| - |
58 |
| -If your component is stateful or you need to use ResizeAware in the middle of one |
59 |
| -of your components you can use the `onResize` property of the component to provide |
60 |
| -a callback that will be called on each resize of the ResizeAware component and will |
61 |
| -provide as first argument an object with `width` and `height` properties. |
62 |
| - |
63 |
| -```jsx |
64 |
| -import React, { Component } from 'react'; |
65 |
| -import ResizeAware from 'react-resize-aware'; |
66 |
| - |
67 |
| -function MyComponent({width, height}) { |
68 |
| - return <div>{width}x{height}</div>; |
69 |
| -} |
70 |
| - |
71 |
| -class MyComponent extend Component { |
72 |
| - handleResize = ({ width, height }) => console.log(width, height); |
73 |
| - |
74 |
| - render() { |
75 |
| - return ( |
76 |
| - <div> |
77 |
| - My app renders... |
78 |
| - <ResizeAware |
79 |
| - style={{ position: 'relative' }} |
80 |
| - onlyEvent |
81 |
| - onResize={this.handleResize} |
82 |
| - > |
83 |
| - <MyComponent /> |
84 |
| - </ResizeAware> |
85 |
| - </div> |
86 |
| - ); |
87 |
| - } |
88 |
| -} |
| 18 | +npm install --save react-resize-aware |
89 | 19 | ```
|
90 | 20 |
|
91 |
| -## Self containing |
| 21 | +## Usage |
92 | 22 |
|
93 |
| -If you need to keep your DOM structure clean and you don't want the additional |
94 |
| -`div` added by ResizeAware, you can use the component as base for your own one. |
| 23 | +The API is simple yet powerful, the `useResizeAware` [Hook](https://reactjs.org/docs/hooks-reference.html) |
| 24 | +returns a component you will place inside the measured element, and an object containing its sizes: |
95 | 25 |
|
96 | 26 | ```jsx
|
97 | 27 | import React from 'react';
|
98 |
| -import ResizeAware from 'react-resize-aware'; |
| 28 | +import useResizeAware from 'react-resize-aware'; |
99 | 29 |
|
100 |
| -// This component will get re-rendered every time its width or height changes |
101 |
| -// It must expose a `getRef` property and must allow its `children` to be rendered |
102 |
| -// as direct descendant |
103 |
| -// The `getRef` property must be assigned to the `ref` property of the main element |
104 |
| -function MyComponent({width, height, getRef, children}) { |
105 |
| - return ( |
106 |
| - <div ref={getRef} style={{ position: 'relative' }}> |
107 |
| - <span>{width}x{height}</span> |
108 |
| - {children} |
109 |
| - </div> |
110 |
| - ); |
111 |
| -} |
| 30 | +const App = () => { |
| 31 | + const [ResizeListener, sizes] = useResizeAware(); |
112 | 32 |
|
113 |
| -function App() { |
114 | 33 | return (
|
115 |
| - <ResizeAware component={MyComponent} /> |
| 34 | + <div style={{ position: 'relative' }}> |
| 35 | + <ResizeListener /> |
| 36 | + Your content here. (div sizes are {sizes.width} x {sizes.height}) |
| 37 | + </div> |
116 | 38 | );
|
117 |
| -} |
| 39 | +}; |
118 | 40 | ```
|
119 | 41 |
|
120 |
| -## Child function |
| 42 | +> **Heads up!**: Make sure to assign a `position != initial` to the HTMLElement you want to target (`relative`, `absolute`, or `fixed` will work). |
121 | 43 |
|
122 |
| -Whenever you want to manipulate the `width` and `height` properties before they |
123 |
| -get passed down to the child component, you can define a function as child of ResizeAware: |
| 44 | +## API |
124 | 45 |
|
125 |
| -```jsx |
126 |
| -import React from 'react'; |
127 |
| -import ResizeAware from 'react-resize-aware'; |
| 46 | +The Hook returns an array with two elements inside: |
128 | 47 |
|
129 |
| -export default makeResizeAware(function MyComponent({width, height, getRef, children})) { |
130 |
| - return ( |
131 |
| - <ResizeAware style={{ position: 'relative' }}> |
132 |
| - {({ width, height }) => |
133 |
| - <div style={{ width: width / 2, height: height / 2 }} />} |
134 |
| - </ResizeAware> |
135 |
| - ); |
136 |
| -}) |
137 |
| -``` |
| 48 | +### `[ResizeListener, ...]` (first element) |
138 | 49 |
|
139 |
| -## Decorator/enhancer |
| 50 | +This is an invisible component that must be placed as direct-child of the HTMLElement you want to listen the resize events of. |
140 | 51 |
|
141 |
| -In case you prefer to directly decorate your component to add to it the ResizeAware |
142 |
| -functionalities, you can do as follow: |
| 52 | +The component is not going to interfer with your layouts, I promise. |
143 | 53 |
|
144 |
| -```jsx |
145 |
| -import React from 'react'; |
146 |
| -import { makeResizeAware } from 'react-resize-aware'; |
| 54 | +### `[..., sizes]` (second element) |
147 | 55 |
|
148 |
| -export default makeResizeAware(function MyComponent({width, height, getRef, children})) { |
149 |
| - return ( |
150 |
| - <div ref={getRef} style={{ position: 'relative' }}> |
151 |
| - <span>{width}x{height}</span> |
152 |
| - {children} |
153 |
| - </div> |
154 |
| - ); |
155 |
| -}) |
156 |
| -``` |
| 56 | +This object contains the `width` and `height` properties, these properties are going to be `null` before the component rendered, and will return a `number` after the component rendered. |
157 | 57 |
|
158 |
| -Or, with ES7 decorators: |
| 58 | +## Custom `reporter` |
| 59 | + |
| 60 | +You can customize the properties of the `sizes` object by passing a custom `reporter` function as first argument of `useResizeAware`. |
159 | 61 |
|
160 | 62 | ```jsx
|
161 |
| -import React from 'react'; |
162 |
| -import { makeResizeAware } from 'react-resize-aware'; |
163 |
| - |
164 |
| -@makeResizeAware |
165 |
| -export default class MyComponent extends React.Component { |
166 |
| - render() { |
167 |
| - const {width, height, getRef, children} = this.props; |
168 |
| - return ( |
169 |
| - <div ref={getRef} style={{ position: 'relative' }}> |
170 |
| - <span>{width}x{height}</span> |
171 |
| - {children} |
172 |
| - </div> |
173 |
| - ); |
174 |
| - } |
175 |
| -} |
| 63 | +const customReporter = element => ({ |
| 64 | + clientWidth: target != null ? target.clientWidth : null, |
| 65 | +}); |
| 66 | + |
| 67 | +const [ResizeListener, sizes] = useResizeAware(customReporter); |
| 68 | + |
| 69 | +return ( |
| 70 | + <div style={{ position: 'relative' }}> |
| 71 | + <ResizeListener /> |
| 72 | + Your content here. (div clientWidth is {sizes.clientWidth}) |
| 73 | + </div> |
| 74 | +); |
176 | 75 | ```
|
177 | 76 |
|
178 |
| - |
179 |
| -## Properties |
180 |
| - |
181 |
| -- The `onlyEvent` property will prevent ResizeAware from passing the `height` and `width` |
182 |
| -properties to its child component, in case you don't want to rely on them. |
183 |
| -- The `component` property allows to define the HTML tag used by ResizeAware to render, or any React component. |
184 |
| -- The `onResize` property is an optional callback called on each resize with as first |
185 |
| - argument an object containing `height` and `width` properties. |
186 |
| -- `widthPropName` and `heightPropName`, set them to change the name of the properties passed to the |
187 |
| - child component, in place of the default `width` and `height` names. |
188 |
| - |
189 |
| -# License |
190 |
| - |
191 |
| -MIT License |
192 |
| -Copyright 2016+, Federico Zivolo |
| 77 | +The above example will report the `clientWidth` rather than the default `offsetWidth` and `offsetHeight`. |
0 commit comments