Skip to content

Commit 52709fe

Browse files
committed
chore: Updated readme and contributing files.
Resolves ZeeCoder#66
1 parent bd0f3c8 commit 52709fe

File tree

2 files changed

+119
-37
lines changed

2 files changed

+119
-37
lines changed

CONTRIBUTING.md

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# CONTRIBUTING
22

3-
When contributing to this project, please keep in mind the following goals:
3+
When contributing to this project, please keep in mind the following:
44

5-
- The hook must remain as simple as possible. It's only a "proxy" to a
6-
ResizeObserver instance, and shouldn't add features that the resize observer
7-
doesn't do.
5+
- The hook must remain as simple as possible. It's only a low-level "proxy" to a
6+
ResizeObserver instance aiming for correctness, which should not add or polyfill
7+
features on top. All that can be done by composing hooks.
88
- All features must be covered with test(s).
99

1010
It's also best to first submit an issue, before creating a pull request so that
@@ -28,10 +28,13 @@ While making changes you might want to watch the source files, and build them
2828
automatically, as well as having Karma run a (non-headless) Chrome instance
2929
every time a change was made.
3030

31-
To do that:
31+
To do so:
3232

3333
- Run `yarn src:watch` in a terminal tab
34-
- Run `KARMA_BROWSERS=Chrome yarn karma:watch` in another.
34+
- Run `yarn karma:watch` in another.
3535

3636
Don't forget to run `yarn test` at the end once you're done with everything, to
3737
make sure the new code is tested for regressions.
38+
39+
If you have a Browserstack account, then you can also run the tests in real browsers using the `test:bs:*` commands.
40+
Just make sure you have the following env variables set: `BS_USERNAME`, `BS_ACCESS_KEY`.

README.md

+110-31
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,18 @@ A React hook that allows you to use a ResizeObserver to measure an element's siz
1616
## Highlights
1717

1818
- Written in **TypeScript**.
19-
- **Tiny**: [500B](.size-limit.json) (minified, gzipped) Monitored by [size-limit](https://github.com/ai/size-limit).
19+
- **Tiny**: [645B](.size-limit.json) (minified, gzipped) Monitored by [size-limit](https://github.com/ai/size-limit).
2020
- Exposes an **onResize callback** if you need more control.
21+
- `box` [option](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/observe#syntax).
2122
- Works with **SSR**.
2223
- Works with **CSS-in-JS**.
2324
- **Supports custom refs** in case you [had one already](#passing-in-your-own-ref).
2425
- **Uses RefCallback by default** To address delayed mounts and changing ref elements.
2526
- **Ships a polyfilled version**
2627
- Handles many edge cases you might not even think of.
2728
(See this documentation and the test cases.)
28-
- [Throttle / Debounce](#throttle--debounce)
29-
- **Tested in real browsers** (Currently latest Chrome, Safari, Firefox and IE 11, sponsored by BrowserStack)
29+
- Easy to compose ([Throttle / Debounce](#throttle--debounce), [Breakpoints](#breakpoints))
30+
- **Tested in real browsers** (Currently latest Chrome, Firefox, Edge, Safari, Opera, IE 11, iOS and Android, sponsored by BrowserStack)
3031

3132
## In Action
3233

@@ -40,6 +41,23 @@ yarn add use-resize-observer --dev
4041
npm install use-resize-observer --save-dev
4142
```
4243

44+
## Options
45+
46+
| Option | Type | Description | Default |
47+
| -------- | ------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- | -------------- |
48+
| ref | undefined | RefObject | HTMLElement | A ref or element to observe. | undefined |
49+
| box | undefined | "border-box" | "content-box" | "device-pixel-content-box" | The [box model](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/observe#syntax) to use for observation. | "content-box" |
50+
| onResize | undefined | ({ width?: number, height?: number }) => void | A callback receiving the element size. If given, then the hook will not return the size, and instead will call this callback. | undefined |
51+
| round | undefined | (n: number) => number | A function to use for rounding values instead of the default. | `Math.round()` |
52+
53+
## Response
54+
55+
| Name | Type | Description |
56+
| ------ | ----------------------- | ---------------------------------------------- |
57+
| ref | RefCallback | A callback to be passed to React's "ref" prop. |
58+
| width | undefined | number | The width (or "blockSize") of the element. |
59+
| height | undefined | number | The height (or "inlineSize") of the element. |
60+
4361
## Basic Usage
4462

4563
Note that the default builds are not polyfilled! For instructions and alternatives,
@@ -60,40 +78,100 @@ const App = () => {
6078
};
6179
```
6280

63-
Note that "ref" here is a `RefCallback`, not a `RefObject`, meaning you won't be
64-
able to access "ref.current" if you need the element itself.
65-
To get the raw element, either you use your own RefObject (see later in this doc)
66-
or you hook in the returned ref callback, like so:
81+
To observe a different box size other than content box, pass in the `box` option, like so:
82+
83+
```tsx
84+
const { ref, width, height } = useResizeObserver<HTMLDivElement>({
85+
box: "border-box",
86+
});
87+
```
88+
89+
Note that if the browser does not support the given box type, then the hook won't report any sizes either.
90+
91+
### Box Options
92+
93+
Note that box options are experimental, and as such are not supported by all browsers that implemented ResizeObservers. (See [here](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry).)
94+
95+
`content-box` (default)
6796

68-
### Getting the raw element from the default `RefCallback`
97+
Safe to use by all browsers that implemented ResizeObservers. The hook internally will fall back to `contentRect` from
98+
the old spec in case `contentBoxSize` is not available.
99+
100+
`border-box`
101+
102+
Supported well for the most part by evergreen browsers. If you need to support older versions of these browsers however,
103+
then you may want to feature-detect for support, and optionally include a polyfill instead of the native implementation.
104+
105+
`device-pixel-content-box`
106+
107+
Surma has a [very good article](https://web.dev/device-pixel-content-box/) on how this allows us to do pixel perfect
108+
rendering. At the time of writing, however this has very limited support.
109+
The advices on feature detection for `border-box` apply here too.
110+
111+
### Custom Rounding
112+
113+
By default this hook passes the measured values through `Math.round()`, to avoid re-rendering on every subpixel changes.
114+
115+
If this is not what you want, then you can provide your own function:
116+
117+
**Rounding Down Reported Values**
69118

70119
```tsx
71-
import React, { useCallback, useEffect, useRef } from "react";
120+
const { ref, width, height } = useResizeObserver<HTMLDivElement>({
121+
round: Math.floor,
122+
});
123+
```
124+
125+
**Skipping Rounding**
126+
127+
```tsx
128+
import React from "react";
72129
import useResizeObserver from "use-resize-observer";
73130

74-
const useMergedCallbackRef = (...callbacks: Function[]) => {
75-
// Storing callbacks in a ref, so that we don't need to memoise them in
76-
// renders when using this hook.
77-
const callbacksRegistry = useRef<Function[]>(callbacks);
131+
// Outside the hook to ensure this instance does not change unnecessarily.
132+
const noop = (n) => n;
78133

79-
useEffect(() => {
80-
callbacksRegistry.current = callbacks;
81-
}, [...callbacks]);
134+
const App = () => {
135+
const {
136+
ref,
137+
width = 1,
138+
height = 1,
139+
} = useResizeObserver<HTMLDivElement>({ round: noop });
82140

83-
return useCallback((element) => {
84-
callbacksRegistry.current.forEach((callback) => callback(element));
85-
}, []);
141+
return (
142+
<div ref={ref}>
143+
Size: {width}x{height}
144+
</div>
145+
);
86146
};
147+
```
148+
149+
Note that the round option is sensitive to the function reference, so make sure you either use `useCallback`
150+
or declare your rounding function outside of the hook's function scope, if it does not rely on any hook state.
151+
(As shown above.)
152+
153+
### Getting the Raw Element from the Default `RefCallback`
154+
155+
Note that "ref" in the above examples is a `RefCallback`, not a `RefObject`, meaning you won't be
156+
able to access "ref.current" if you need the element itself.
157+
158+
To get the raw element, either you use your own RefObject (see later in this doc),
159+
or you can merge the returned ref with one of your own:
160+
161+
```tsx
162+
import React, { useCallback, useEffect, useRef } from "react";
163+
import useResizeObserver from "use-resize-observer";
164+
import mergeRefs from "react-merge-refs";
87165

88166
const App = () => {
89167
const { ref, width = 1, height = 1 } = useResizeObserver<HTMLDivElement>();
90168

91-
const mergedCallbackRef = useMergedCallbackRef(
169+
const mergedCallbackRef = mergeRefs([
92170
ref,
93171
(element: HTMLDivElement) => {
94172
// Do whatever you want with the `element`.
95-
}
96-
);
173+
},
174+
]);
97175

98176
return (
99177
<div ref={mergedCallbackRef}>
@@ -128,13 +206,13 @@ const { width, height } = useResizeObserver<HTMLDivElement>({
128206
});
129207
```
130208

131-
## Using a single hook to measure multiple refs
209+
## Using a Single Hook to Measure Multiple Refs
132210

133211
The hook reacts to ref changes, as it resolves it to an element to observe.
134212
This means that you can freely change the custom `ref` option from one ref to
135213
another and back, and the hook will start observing whatever is set in its options.
136214

137-
## Opting Out of (or Delaying) ResizeObserver instantiation
215+
## Opting Out of (or Delaying) ResizeObserver Instantiation
138216

139217
In certain cases you might want to delay creating a ResizeObserver instance.
140218

@@ -156,7 +234,7 @@ You can do one of the following depending on your needs:
156234
(This assumes you don't already use the polyfilled version, which would switch
157235
to the polyfill when no native implementation was available.)
158236

159-
## The "onResize" callback
237+
## The "onResize" Callback
160238

161239
By the default the hook will trigger a re-render on all changes to the target
162240
element's width and / or height.
@@ -188,12 +266,13 @@ what you need, for example:
188266
- Throttle / debounce
189267
- Wrap in `requestAnimationFrame`
190268

191-
## Throttle / Debounce
269+
## Hook Composition
192270

193-
You might want to receive values less frequently than changes actually occur.
271+
As this hook intends to remain low-level, it is encouraged to build on top of it via hook composition, if additional features are required.
272+
273+
### Throttle / Debounce
194274

195-
While this hook does not come with its own implementation of throttling / debouncing,
196-
you can use the `onResize` callback to implement your own version:
275+
You might want to receive values less frequently than changes actually occur.
197276

198277
[CodeSandbox Demo](https://codesandbox.io/s/use-resize-observer-throttle-and-debounce-8uvsg)
199278

@@ -250,8 +329,8 @@ import useResizeObserver from "use-resize-observer/polyfilled";
250329

251330
Note that using the above will use the polyfill, [even if the native ResizeObserver is available](https://github.com/juggle/resize-observer#basic-usage).
252331

253-
To use the polyfill as a fallback instead only when the native RO is unavailable, you can polyfill yourself instead,
254-
either in your app's entry file, or you could create a local useResizeObserver module, like so:
332+
To use the polyfill as a fallback only when the native RO is unavailable, you can polyfill yourself instead,
333+
either in your app's entry file, or you could create a local `useResizeObserver` module, like so:
255334

256335
```ts
257336
// useResizeObserver.ts

0 commit comments

Comments
 (0)