Skip to content

Commit 7141ff7

Browse files
authored
Merge pull request #12 from rob2d/next
new options interface, documentation and examples
2 parents f3dce69 + 5d819ba commit 7141ff7

File tree

9 files changed

+183
-115
lines changed

9 files changed

+183
-115
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
node_modules
2+
media

README.md

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
![npm](https://img.shields.io/npm/v/use-viewport-sizes.svg?color=blue) ![David](https://img.shields.io/david/rob2d/use-viewport-sizes.svg) ![npm](https://img.shields.io/npm/dw/use-viewport-sizes.svg?color=red) ![GitHub issues](https://img.shields.io/github/issues-raw/rob2d/use-viewport-sizes.svg) ![NPM](https://img.shields.io/npm/l/use-viewport-sizes.svg)
44

5-
a tiny React hook which allows you to track visible window viewport size in your components w/ an optional debounce or custom memo function for updates for optimal rendering.
5+
a tiny React hook which allows you to track visible window viewport size in your components w/ an optional debounce and
6+
other flexible options for optimal usage.
67

78
## Installation ##
89

@@ -11,8 +12,8 @@ npm install -D use-viewport-sizes
1112
```
1213

1314
## Benefits ##
14-
- extremely lightweight and dependency-free -- **3.75kb** without/before gzipping.
15-
- only one `window.onresize` handler used to subscribe to any changes in an unlimited number of components as well despite several different paradigms that pull from this.
15+
- extremely lightweight and zero dependencies -- adds **1.6kb** after gzip.
16+
- only one `window.onresize` handler used to subscribe to any changes in an unlimited number of components no matter the use-cases.
1617
- optional debounce to delay updates until user stops dragging their window for a moment; this can make expensive components with size-dependent calculations run much faster and your app feel smoother.
1718
- debouncing does not create new handlers or waste re-renders in your component; the results are also pooled from only one resize result.
1819
- optional hash function to update component subtree only at points you would like to.
@@ -26,12 +27,11 @@ npm install -D use-viewport-sizes
2627
<center>
2728
<img src="./doc/use-viewport-sizes.gif" />
2829

29-
*Interact with the example shown on CodeSandox* @
30-
[https://codesandbox.io/s/react-hooks-viewport-sizes-demo-forked-7rr9c](https://codesandbox.io/s/react-hooks-viewport-sizes-demo-forked-7rr9c)
30+
[CodeSandbox IDE](https://codesandbox.io/s/react-hooks-viewport-sizes-demo-forked-i8urr)
3131

3232
</center>
3333

34-
### **Without Debouncing**
34+
### **Basic Use-case**
3535
*registers dimension changes on every resize event immediately*
3636

3737
```js
@@ -45,29 +45,49 @@ function MyComponent(props) {
4545
}
4646
```
4747

48+
### **Measure/Update only on one dimension**
49+
50+
If passed `options.dimension` as `w` or `h`, only the viewport width or height will be
51+
measured and observed for updates.
52+
The only dimension returned in the return array value will be the width or height, according
53+
to what was passed.
54+
55+
```js
56+
import React from 'react';
57+
import useViewportSizes from 'use-viewport-sizes';
58+
59+
function MyComponent(props) {
60+
const [vpHeight] = useViewportSizes({ dimension: 'h' });
61+
62+
...renderLogic
63+
}
64+
```
65+
4866

4967
### **With Debouncing**
5068

51-
If passed a number as the first argument, it registers dimension changes only when a user stops dragging/resizing the window for a specified number of miliseconds. This is useful for listening to expensive components such as data grids which may be too
69+
If passed `options.debounceTimeout`, or options are entered as a `Number`, it registers dimension changes only when a user stops dragging/resizing the window for a specified number of miliseconds. This is useful for listening to expensive components such as data grids which may be too
5270
expensive to re-render during window resize dragging.
71+
5372
```js
54-
import React from 'react'
55-
import useViewportSizes from 'use-viewport-sizes'
73+
import React from 'react';
74+
import useViewportSizes from 'use-viewport-sizes';
5675

57-
function MyExpensivelyRenderedComponent (props) {
58-
const [vpWidth, vpHeight] = useViewportSizes(1000); // 1s debounce
76+
function MyExpensivelyRenderedComponent(props) {
77+
const [vpWidth, vpHeight] = useViewportSizes({ debounceTimeout: 1000 }); // 1s debounce
5978

60-
...renderLogic
79+
// ...renderLogic
6180
}
6281
```
6382

6483
### **Only update vpW/vpH passed on specific conditions**
65-
If passed a function as the first argument, it will use this to calculate a hash that only updates the viewport when the calculation changes. In the example here, we are using it to detect when we have a breakpoint change which may change how a component is rendered if this is not fully possible or inconvenient via CSS `@media` queries. The hash will also be available as the 3rd value returned from the hook for convenience.
84+
If passed an `options.hasher` function, this will be used to calculate a hash that only updates the viewport when the calculation changes. In the example here, we are using it to detect when we have a breakpoint change which may change how a component is rendered if this is not fully possible or inconvenient via CSS `@media` queries. The hash will also be available as the 3rd value returned from the hook for convenience.
85+
6686
```js
6787
import React from 'react';
6888
import useViewportSizes from 'use-viewport-sizes';
6989

70-
function getBreakpoint({ vpW, vpH }) {
90+
function getBreakpointHash({ vpW, vpH }) {
7191
if(vpW < 640) {
7292
return 'md';
7393
}
@@ -83,7 +103,7 @@ function getBreakpoint({ vpW, vpH }) {
83103
}
84104

85105
function MyBreakpointBehaviorComponent() {
86-
const [vpW, vpH, bp] = useViewportSizes(getBreakpoint);
106+
const [vpW, vpH, bp] = useViewportSizes({ hasher: getBreakpointHash });
87107

88108
// do-something-with-breakpoints in render
89109
// and add new update for vpW, vpH in this component's
@@ -94,24 +114,24 @@ function MyBreakpointBehaviorComponent() {
94114

95115
### **Server Side Rendering**
96116

97-
*While serverside rendering is supported, it requires an explicit update via `useEffect` since viewport does not actually exist on the server before rendering to client. The following has been tested with [NextJS](https://nextjs.org/).*
117+
*Note: While serverside rendering is supported, it requires an explicit update via `useEffect` since viewport does not actually exist on the server before rendering to client. The following has been tested with [NextJS](https://nextjs.org/).*
98118

99-
*Sidenote that you will see a `useLayoutEffect` warning from React. This is perfectly normal as there is no viewport/context to paint to when pre-rendering in SSR and will not interfere with your app once served to the client*
119+
*Sidenote that you will see a `useLayoutEffect` warning from React. This is perfectly expected as there is no viewport/context to paint to when pre-rendering in SSR and will not interfere with your app once served to the client*
100120

101121
```js
102122
import React, { useLayoutEffect } from 'react'
103123
import useViewportSizes from 'use-viewport-sizes'
104124

105125
function MySSRComponent (props) {
106-
const [vpWidth, vpHeight, updateVpSizes] = useViewportSizes()
126+
const [vpW, vpH, updateVpSizes] = useViewportSizes();
107127

108128
// below, we add one post-render update
109129
// in order to register the client's viewport sizes
110130
// after serving SSR content
111131

112-
useEffect(()=> { updateVpSizes(); }, []);
132+
useEffect(()=> { updateVpSizes() }, []);
113133

114-
...renderLogic
134+
// ...renderLogic
115135
}
116136
```
117137

build/index.d.ts

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
declare module 'use-viewport-sizes' {
2+
export type VPSizesHasher = ({ vpW: number, vpH: number }) => String;
3+
export type VPSizesOptions ={
4+
debounceTimeout?: number,
5+
hasher?: VPSizesHasher,
6+
dimension?: 'w'|'h'|'both' = 'both'
7+
};
8+
29
/**
310
* Hook which observes viewport dimensions. Returns [width, height] of
4-
* current visible viewport of app.
5-
*
6-
* If no input specified, returns the [width, height] when the window changes.
7-
*
8-
* If input is specified as a number, it interprets this as the number of
9-
* miliseconds to debounce before updates.
10-
*
11-
* If the input is specified as a function, it accepts a callback
12-
* with the viewport width and height passed in the first arg as
13-
* { vpW, vpH }, and will only return a new value and update when
14-
* the hash-value returned changes.
11+
* current visible viewport of app, or the specific dimension
1512
*/
1613
export default function(
17-
input:number | (({ vpW: number, vpH: number }) => String)
18-
):[vpW: number, vpH: number];
14+
input:number | VPSizesHasher | VPSizesOptions
15+
):([vpW: number, vpH: number, triggerResize: Function] |
16+
[dimension: number, triggerResize:Function]
17+
);
1918
}

build/index.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

doc/use-viewport-sizes.gif

6.01 MB
Loading

package-lock.json

Lines changed: 10 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
{
22
"name": "use-viewport-sizes",
3-
"version": "0.2.12",
3+
"version": "0.3.0",
44
"description": "a tiny React hook which allows you to track visible window viewport size in your components w/ an optional debounce or custom memo function for updates for optimal rendering.",
55
"main": "./build/index.js",
66
"types": "./build/index.d.ts",
77
"scripts": {
88
"start": "webpack --watch",
99
"build": "webpack",
10-
"dev": "webpack-dev-server --env testServer --mode development --open"
10+
"dev": "webpack-dev-server --env testServer --mode development --open",
11+
"prepublishOnly": "npm run build"
1112
},
12-
"peerDependencies": {
13+
"peer Dependencies": {
1314
"react": "^16.8.6"
1415
},
1516
"devDependencies": {

src/index.d.ts

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
declare module 'use-viewport-sizes' {
2+
export type VPSizesHasher = ({ vpW: number, vpH: number }) => String;
3+
export type VPSizesOptions ={
4+
debounceTimeout?: number,
5+
hasher?: VPSizesHasher,
6+
dimension?: 'w'|'h'|'both' = 'both'
7+
};
8+
29
/**
310
* Hook which observes viewport dimensions. Returns [width, height] of
4-
* current visible viewport of app.
5-
*
6-
* If no input specified, returns the [width, height] when the window changes.
7-
*
8-
* If input is specified as a number, it interprets this as the number of
9-
* miliseconds to debounce before updates.
10-
*
11-
* If the input is specified as a function, it accepts a callback
12-
* with the viewport width and height passed in the first arg as
13-
* { vpW, vpH }, and will only return a new value and update when
14-
* the hash-value returned changes.
11+
* current visible viewport of app, or the specific dimension
1512
*/
1613
export default function(
17-
input:number | (({ vpW: number, vpH: number }) => String)
18-
):[vpW: number, vpH: number];
14+
input:number | VPSizesHasher | VPSizesOptions
15+
):([vpW: number, vpH: number, triggerResize: Function] |
16+
[dimension: number, triggerResize:Function]
17+
);
1918
}

0 commit comments

Comments
 (0)