Skip to content

Commit 8fc7e8b

Browse files
committed
v0.2.5: simpler implementation, fix issues and smaller size
1 parent 246bd46 commit 8fc7e8b

File tree

4 files changed

+39
-48
lines changed

4 files changed

+39
-48
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ npm install -D use-viewport-sizes
99
```
1010

1111
## Benefits
12-
- extremely lightweight and dependency-free; **2.59kb pre-gzipped** with all dependencies.
12+
- extremely lightweight and dependency-free -- **2.25kb with no gzip compression**
1313
- only one `window.onresize` handler used to subscribe to any changes in an unlimited number of components.
1414
- 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.
1515
- debouncing does not create new handlers or waste re-renders in your component; the results are also pooled from only one resize result.

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.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "use-viewport-sizes",
3-
"version": "0.2.3",
3+
"version": "0.2.5",
44
"description": "tiny React hook which allows you to track visible window viewport size in your components w/ an optional debounce for updates for optimal rendering.",
55
"main": "build/index.js",
66
"scripts": {

src/index.js

Lines changed: 36 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,16 @@
1-
import { useState, useEffect, useLayoutEffect, useMemo } from "react"
2-
3-
// Note: not using pure ES6/7 as babel
4-
// transpilation eats into precious
5-
// bytes and we're being petty here 🙂
6-
7-
var { documentElement } = window.document;
1+
import { useState, useRef, useLayoutEffect, useMemo } from "react"
82

93
function getVpWidth () {
104
return (typeof window != 'undefined') ? Math.max(
11-
documentElement.clientWidth,
5+
window.document.documentElement.clientWidth,
126
window.innerWidth || 0
137
) : 0;
148
}
159

1610

1711
function getVpHeight () {
1812
return (typeof window != 'undefined') ? Math.max(
19-
documentElement.clientHeight,
13+
window.document.documentElement.clientHeight,
2014
window.innerHeight || 0
2115
) : 0;
2216
}
@@ -29,64 +23,61 @@ function getVpHeight () {
2923
// transpilation saves a bit of filesize
3024

3125
var listeners = new Set();
32-
var vpW = 0;
33-
var vpH = 0;
34-
35-
let hasListenerBeenAttached = false;
36-
26+
var vpW = getVpWidth();
27+
var vpH = getVpHeight();
3728

3829
// should only be called by *one* component once;
3930
// will iterate through all subscribers
4031
// afterwards
4132

4233
function onResize() {
43-
let vpWidth = getVpWidth();
44-
let vpHeight = getVpHeight();
34+
vpW = getVpWidth();
35+
vpH = getVpHeight();
36+
4537
listeners.forEach(function(listener) {
46-
listener({ vpWidth, vpHeight });
38+
listener({ vpWidth : vpW, vpHeight : vpH });
4739
});
4840
}
4941

50-
51-
5242
// =============== //
5343
// the Hook //
5444
// =============== //
5545

5646
function useViewportSizes(debounce) {
47+
const [{ vpWidth, vpHeight }, setState] = useState(()=> ({
48+
vpWidth : vpW,
49+
vpHeight : vpH
50+
}));
51+
const timeout = useRef(undefined);
52+
const listener = useMemo(()=> (!debounce ?
53+
state => setState(state) :
54+
state => {
55+
if(timeout.current) {
56+
clearTimeout(timeout.current);
57+
}
58+
timeout.current = setTimeout(()=>
59+
setState(state), debounce
60+
);
61+
}
62+
), [debounce, setState]);
63+
5764
useLayoutEffect(()=> {
58-
if(window && !hasListenerBeenAttached) {
59-
hasListenerBeenAttached = true;
65+
listeners.add(listener);
66+
67+
if(window && listeners.size == 1) {
6068
window.addEventListener('resize', onResize);
6169
onResize();
6270
}
63-
}, []);
6471

65-
const [{ vpWidth, vpHeight }, setState] = useState(() => ({
66-
vpWidth : vpW, vpHeight : vpH
67-
}));
68-
69-
const listener = useMemo(()=> {
70-
listeners.delete(listener);
72+
// clean up listeners on unmount
7173

72-
let interval = undefined;
74+
return () => {
75+
listeners.delete(listener);
7376

74-
return !debounce ?
75-
state => setState({ ...state }) :
76-
state => {
77-
if(interval) {
78-
clearTimeout(interval);
79-
}
80-
interval = setTimeout(()=>
81-
setState({ ...state }),
82-
debounce
83-
);
84-
};
85-
}, [debounce, setState]);
86-
87-
useEffect(() => {
88-
listeners.add(listener);
89-
return () => listeners.delete(listener);
77+
if(listeners.size == 0) {
78+
window.removeEventListener('resize', onResize);
79+
}
80+
};
9081
}, []);
9182

9283
return [vpWidth, vpHeight, onResize];

0 commit comments

Comments
 (0)