Skip to content

Commit 78bed9d

Browse files
authored
Merge pull request #39 from rob2d/feature/bitwise-dimension-hashes
updates: optimize dimension hashing ~50x & reduce build size by half
2 parents 7a4cfcd + 9a522ec commit 78bed9d

File tree

5 files changed

+70
-41
lines changed

5 files changed

+70
-41
lines changed

.babelrc

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,31 @@
11
{
22
"presets": [
3-
"@babel/preset-env"
3+
[
4+
"@babel/preset-env",
5+
{
6+
"targets": {
7+
"browsers": "last 2 versions, not ie 11",
8+
"node": "20"
9+
},
10+
"exclude": [
11+
"@babel/plugin-proposal-optional-chaining",
12+
"transform-destructuring",
13+
"transform-typeof-symbol",
14+
"transform-parameters",
15+
"transform-for-of",
16+
"transform-regenerator",
17+
"transform-object-rest-spread"
18+
]
19+
}
20+
]
21+
],
22+
"plugins": [
23+
[
24+
"@babel/plugin-transform-runtime",
25+
{
26+
"helpers": true,
27+
"regenerator": false
28+
}
29+
]
430
]
531
}

README.md

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,19 @@
44
![Github Workflow Status](https://github.com/rob2d/use-viewport-sizes/actions/workflows/node.js.yml/badge.svg)
55
[![NPM](https://img.shields.io/npm/l/use-viewport-sizes.svg)](https://github.com/rob2d/use-viewport-sizes/blob/master/LICENSE)
66

7-
a tiny TS-compatible React hook which allows you to track visible window viewport size in your components w/ an optional debounce, throttle or custom memo function for updates for optimal rendering.
7+
A lightweight, TypeScript-compatible React hook for tracking viewport sizes in your components. Includes optional debounce, throttle, and custom memoization for optimized rendering.
8+
9+
## Table of Contents
10+
- [Installation](#installation)
11+
- [Benefits](#benefits)
12+
- [Usage](#usage)
13+
- [Basic Use-case](#basic-use-case)
14+
- [Measure/Update only on one dimension](#measureupdate-only-on-one-dimension)
15+
- [With Throttling](#with-throttling)
16+
- [With Debouncing](#with-debouncing)
17+
- [Only update vpW/vpH passed on specific conditions](#only-update-vpwvph-passed-on-specific-conditions)
18+
- [Support](#support)
19+
- [License](#license)
820

921
## Installation ##
1022

@@ -13,7 +25,7 @@ npm install -D use-viewport-sizes
1325
```
1426

1527
## Benefits ##
16-
- extremely lightweight and zero dependencies -- adds **2.04kb** after gzip.
28+
- extremely lightweight and zero dependencies -- adds **2.38kb** pre gzip, and **1.09kb** after gzip.
1729
- only one `window.onresize` handler used to subscribe to any changes in an unlimited number of components no matter the use-cases.
1830
- 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.
1931
- debouncing does not create new handlers or waste re-renders in your component; the results are also pooled from only one resize result.
@@ -125,4 +137,4 @@ Otherwise, if this was useful and you'd like to show your support, no donations
125137

126138
## License ##
127139

128-
- Open Source **[MIT license](http://opensource.org/licenses/mit-license.php)**
140+
Open Source **[MIT license](http://opensource.org/licenses/mit-license.php)**

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
{
22
"name": "use-viewport-sizes",
3-
"version": "0.7.3",
3+
"version": "0.8.0",
44
"description": "a tiny TS-compatible React hook which allows you to track visible window viewport size in your components w/ an optional debounce, throttle 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 --mode development",
99
"build": "webpack --mode production",
10+
"build:babel": "babel src --out-dir build --extensions \".js\"",
1011
"dev": "webpack-dev-server --env testServer --mode development --open",
1112
"prepublishOnly": "npm run build",
1213
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage"

src/index.js

Lines changed: 25 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,18 @@ import {
77
} from 'react';
88

99
function getVpWidth() {
10-
return (typeof window != 'undefined') ? Math.max(
11-
window.document.documentElement.clientWidth,
12-
window.innerWidth || 0
13-
) : 0;
10+
return Math.max(
11+
globalThis?.document?.documentElement?.clientWidth || 0,
12+
globalThis?.innerWidth || 0
13+
);
1414
}
1515

1616

1717
function getVpHeight() {
18-
return (typeof window != 'undefined') ? Math.max(
19-
window.document.documentElement.clientHeight,
20-
window.innerHeight || 0
21-
) : 0;
18+
return Math.max(
19+
globalThis?.document?.documentElement?.clientHeight || 0,
20+
globalThis?.innerHeight || 0
21+
);
2222
}
2323

2424
// Avoid useLayoutEffect warning during SSR
@@ -68,40 +68,35 @@ let vpHeight = getVpHeight();
6868
*/
6969
function triggerResizeListener(listener, vpWidth, vpHeight) {
7070
const params = { vpW: vpWidth, vpH: vpHeight };
71-
72-
let shouldRun = false;
7371
let hash;
7472

7573
const { options, prevHash=undefined } = resolverMap?.get(listener) || {};
76-
const { hasher } = options;
7774

78-
if(!hasher) {
75+
if(!options.hasher) {
7976
switch (options?.dimension) {
8077
case 'w':
81-
hash = `${vpWidth}`;
78+
hash = vpWidth;
8279
break;
8380
case 'h':
84-
hash = `${vpHeight}`;
81+
hash = vpHeight;
8582
break;
8683
default:
87-
case 'both':
88-
hash = `${vpWidth}_${vpHeight}`;
84+
hash = (vpWidth << 16) | vpHeight;
8985
break;
9086
}
9187
}
9288
else {
93-
hash = hasher(params);
89+
hash = options.hasher(params);
9490
}
9591

96-
if(hash != prevHash) { shouldRun = true }
97-
98-
if(shouldRun) {
92+
if(hash != prevHash) {
9993
const state = { ...params, options, hash };
10094
resolverMap.set(listener, {
10195
options,
10296
prevHash: hash,
10397
prevState: state
10498
});
99+
105100
listener(state);
106101
}
107102
}
@@ -126,13 +121,6 @@ function onResize() {
126121
// the Hook //
127122
// =============== //
128123

129-
function getInitialState(options, vpW, vpH) {
130-
return (!options.hasher ?
131-
{ vpW, vpH } :
132-
options.hasher({ vpW: vpWidth, vpH: vpHeight })
133-
)
134-
}
135-
136124
export default function useViewportSizes(input) {
137125
const hasher = ((typeof input == 'function') ?
138126
input :
@@ -156,7 +144,10 @@ export default function useViewportSizes(input) {
156144
hasher
157145
};
158146

159-
const [state, setState] = useState(() => getInitialState(options));
147+
const [state, setState] = useState(() => {
148+
const defaultState = { vpW: vpWidth, vpH: vpHeight };
149+
return options.hasher ? options.hasher(defaultState) : defaultState;
150+
});
160151
const debounceTimeoutRef = useRef(undefined);
161152
const throttleTimeoutRef = useRef(undefined);
162153
const lastThrottledRef = useRef(undefined);
@@ -247,25 +238,24 @@ export default function useViewportSizes(input) {
247238
switch (dimension) {
248239
default:
249240
case 'both': {
250-
dimensionHash = `${state?.vpW}_${state.vpH}`;
241+
dimensionHash = `${state.vpW}_${state.vpH}`;
251242
break;
252243
}
253244
case 'w': {
254-
dimensionHash = state?.vpW || 0;
245+
dimensionHash = state.vpW || 0;
255246
break;
256247
}
257248
case 'h': {
258-
dimensionHash = state?.vpH || 0;
249+
dimensionHash = state.vpH || 0;
259250
break;
260251
}
261252
}
262253

263254
const returnValue = useMemo(() => {
264255
switch (dimension) {
265-
default:
266-
case 'both': { return [state?.vpW || 0, state?.vpH || 0, onResize] }
267-
case 'w': { return [state?.vpW || 0, onResize] }
268-
case 'h': { return [state?.vpH || 0, onResize] }
256+
default: { return [state.vpW || 0, state.vpH || 0, onResize] }
257+
case 'w': { return [state.vpW || 0, onResize] }
258+
case 'h': { return [state.vpH || 0, onResize] }
269259
}
270260
}, [dimensionHash, onResize, dimension]);
271261

webpack.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ module.exports = {
1515
include: path.resolve(__dirname, 'src'),
1616
exclude: /(node_modules|bower_components|build)/,
1717
use: {
18-
loader: 'babel-loader'
18+
loader: 'babel-loader',
1919
}
2020
}
2121
]

0 commit comments

Comments
 (0)