Skip to content

Commit 62d5032

Browse files
authored
feat: new React Hooks API (#17)
feat: new React hooks API
1 parent 7752f43 commit 62d5032

17 files changed

+2903
-3268
lines changed

.babelrc

-3
This file was deleted.

.editorconfig

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
root = true
2+
3+
[*]
4+
end_of_line = lf
5+
insert_final_newline = true
6+
indent_style = space
7+
indent_size = 2

.flowconfig

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[ignore]
2+
3+
[include]
4+
5+
[libs]
6+
7+
[lints]
8+
9+
[options]
10+
11+
[strict]

.npmignore

-2
This file was deleted.

README.md

+41-156
Original file line numberDiff line numberDiff line change
@@ -1,192 +1,77 @@
11
# react-resize-aware
22

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.
44

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.
96

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.**
138

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
1910

2011
```
2112
yarn add react-resize-aware
22-
# or
23-
npm install --save react-resize-aware
2413
```
2514

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:
3716

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-
}
5417
```
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
8919
```
9020

91-
## Self containing
21+
## Usage
9222

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:
9525

9626
```jsx
9727
import React from 'react';
98-
import ResizeAware from 'react-resize-aware';
28+
import useResizeAware from 'react-resize-aware';
9929

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();
11232

113-
function App() {
11433
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>
11638
);
117-
}
39+
};
11840
```
11941

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).
12143
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
12445

125-
```jsx
126-
import React from 'react';
127-
import ResizeAware from 'react-resize-aware';
46+
The Hook returns an array with two elements inside:
12847

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)
13849

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.
14051

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.
14353

144-
```jsx
145-
import React from 'react';
146-
import { makeResizeAware } from 'react-resize-aware';
54+
### `[..., sizes]` (second element)
14755

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.
15757

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`.
15961

16062
```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+
);
17675
```
17776

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`.

docs/example.js

-64
This file was deleted.

docs/index.html

+24-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
sans-serif;
1111
}
1212
.example {
13+
position: relative;
1314
background-color: rebeccapurple;
1415
height: 100px;
1516
width: 100%;
@@ -25,9 +26,29 @@
2526
<body>
2627
<div id="root"></div>
2728
<a href="https://github.com/fezvrasta/react-resize-aware">GitHub page</a>
28-
<script src="https://unpkg.com/[email protected]/umd/react.production.min.js"></script>
29-
<script src="https://unpkg.com/[email protected]/umd/react-dom.production.min.js"></script>
29+
<script src="https://unpkg.com/[email protected]/umd/react.production.min.js"></script>
30+
<script src="https://unpkg.com/[email protected]/umd/react-dom.production.min.js"></script>
31+
<script src="https://unpkg.com/[email protected]/babel.min.js"></script>
3032
<script src="./react-resize-aware.js"></script>
31-
<script src="./example.js"></script>
33+
<script type="text/babel">
34+
const App = () => {
35+
const reporter = target => ({
36+
width: target != null ? target.offsetWidth : null,
37+
height: target != null ? target.offsetHeight : null,
38+
clientWidth: target != null ? target.clientWidth : null,
39+
});
40+
41+
const [ResizeListener, sizes] = useResizeAware(reporter);
42+
43+
return (
44+
<div className="example">
45+
<ResizeListener />
46+
Your content here. (div sizes are {sizes.width} x {sizes.height}, clientWidth is {sizes.clientWidth}px)
47+
</div>
48+
);
49+
};
50+
51+
ReactDOM.render(<App />, document.querySelector('#root'));
52+
</script>
3253
</body>
3354
</html>

0 commit comments

Comments
 (0)