Skip to content

Commit bb6f662

Browse files
committed
v6.2.0-alpha1 release
1 parent 9656441 commit bb6f662

File tree

14 files changed

+641
-202
lines changed

14 files changed

+641
-202
lines changed

.size-limit.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,32 @@
11
[
22
{
33
"path": "dist/bundle.esm.js",
4-
"limit": "357 B",
4+
"limit": "499 B",
55
"gzip": true
66
},
77
{
88
"path": "dist/bundle.esm.js",
9-
"limit": "281 B",
9+
"limit": "404 B",
1010
"brotli": true
1111
},
1212
{
1313
"path": "dist/bundle.cjs.js",
14-
"limit": "346 B",
14+
"limit": "485 B",
1515
"gzip": true
1616
},
1717
{
1818
"path": "dist/bundle.cjs.js",
19-
"limit": "261 B",
19+
"limit": "387 B",
2020
"brotli": true
2121
},
2222
{
2323
"path": "polyfilled.js",
24-
"limit": "2678 B",
24+
"limit": "2809 B",
2525
"gzip": true
2626
},
2727
{
2828
"path": "polyfilled.js",
29-
"limit": "2381 B",
29+
"limit": "2512 B",
3030
"brotli": true
3131
}
3232
]

CHANGELOG.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,27 @@
11
# CHANGELOG
22

3+
## 6.2.0-alpha1
4+
5+
- Only instantiating a ResizeObserver instance if there's actually something to
6+
observe. This for example means that if you pass in `null` or undefined as the
7+
ref, or if neither the default ref or callback ref returned from the hook are
8+
in use, then no ResizeObserver instance will get created until there's an
9+
actual element to observe. Resolves: #42
10+
- The hook now returns `callbackRef`, which can be used in place of the usual
11+
`ref`. Use this instead of a normal ref, when the observed component is
12+
mounted with a delay. Resolves: #43, #45
13+
- The `ref` option now accepts raw elements as well.
14+
- Handling custom refs (through options), the default ref and the callback ref
15+
has been greatly refactored internally (into the `useResolvedElement`
16+
hook), to handle more edge cases with the way refs are handled.
17+
- Tests based on react testing library were refactored to make them much simpler
18+
and more approachable.
19+
- Fixed an error where in certain edge cases the hook tried to set state when
20+
its host component already unmounted.
21+
- Added [contributing guidelines](./CONTRIBUTING.md)
22+
- Overall bundle size increased a bit, due to the new features added.
23+
(With about ~150B or so.)
24+
325
## 6.1.0
426

527
- No changes, only publishing the next minor.

CONTRIBUTING.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# CONTRIBUTING
2+
3+
When contributing to this project, please keep in mind the following goals:
4+
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.
8+
- All features must be covered with test(s).
9+
10+
It's also best to first submit an issue, before creating a pull request so that
11+
the required feature can be discussed, as well as the actual implementation.
12+
13+
## Adding a New Feature
14+
15+
- Open an issue, so that a discussion can take place,
16+
- Once discussed, add the changes to `src/index.ts` accordingly (make sure TS
17+
types are respected as well),
18+
- Add new test(s) to cover the new feature in: `test/testing-lib.tsx`.
19+
Ignore the other test files, as they're fairly old and much harder to add new
20+
ones to them compared to just using react testing lib.
21+
- Run all the tests to ensure there are no regressions: `yarn test`,
22+
23+
## Using Watch Modes While Developing
24+
25+
There are other test-related scripts in package.json, to enhance the developer
26+
experience.
27+
While making changes you might want to watch the source files, and build them
28+
automatically, as well as having Karma run a (non-headless) Chrome instance
29+
every time a change was made.
30+
31+
To do that:
32+
33+
- Run `yarn src:watch` in a terminal tab
34+
- Run `KARMA_BROWSERS=Chrome yarn karma:watch` in another.
35+
36+
Don't forget to run `yarn test` at the end once you're done with everything, to
37+
make sure the new code is tested for regressions.

README.md

Lines changed: 92 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ A React hook that allows you to use a ResizeObserver to measure an element's siz
1515
## Highlights
1616

1717
- Written in **TypeScript**.
18-
- **Tiny**: 353 B (minified, gzipped) Monitored by [size-limit](https://github.com/ai/size-limit).
18+
- **Tiny**: 500B (minified, gzipped) Monitored by [size-limit](https://github.com/ai/size-limit).
1919
- Exposes an **onResize callback** if you need more control.
20-
- [Throttle / Debounce](#throttle--debounce)
2120
- Works with **SSR**.
2221
- Works with **CSS-in-JS**.
2322
- **Supports custom refs** in case you [had one already](#passing-in-your-own-ref).
23+
- Handles many edge cases you might not even think of.
24+
(See this documentation and the test cases.)
25+
- [Throttle / Debounce](#throttle--debounce)
2426
- **Tested** in real browsers. (Headless Chrome and Firefox).
2527

2628
## In Action
@@ -40,12 +42,12 @@ npm install use-resize-observer --save-dev
4042
Note that the default builds are not polyfilled! For instructions and alternatives,
4143
see the [Transpilation / Polyfilling](#transpilation--polyfilling) section.
4244

43-
```js
45+
```tsx
4446
import React from "react";
4547
import useResizeObserver from "use-resize-observer";
4648

4749
const App = () => {
48-
const { ref, width = 1, height = 1 } = useResizeObserver();
50+
const { ref, width = 1, height = 1 } = useResizeObserver<HTMLDivElement>();
4951

5052
return (
5153
<div ref={ref}>
@@ -60,15 +62,92 @@ const App = () => {
6062
You can pass in your own ref instead of using the one provided.
6163
This can be useful if you already have a ref you want to measure.
6264

63-
```js
64-
const ref = useRef(null);
65-
const { width, height } = useResizeObserver({ ref });
65+
```ts
66+
const ref = useRef<HTMLDivElement>(null);
67+
const { width, height } = useResizeObserver<HTMLDivElement>({ ref });
6668
```
6769

6870
You can even reuse the same hook instance to measure different elements:
6971

7072
[CodeSandbox Demo](https://codesandbox.io/s/use-resize-observer-reusing-refs-buftd)
7173

74+
## Measuring a raw element
75+
76+
There might be situations where you have an element already that you need to measure.
77+
`ref` now accepts elements as well, not just refs, which means that you can do this:
78+
79+
```ts
80+
const { width, height } = useResizeObserver<HTMLDivElement>({
81+
ref: divElement,
82+
});
83+
```
84+
85+
## Observing components mounted with a delay
86+
87+
Often times you might have to wait before you can mount a component.
88+
Unfortunately if you use a ref, the hook will not be able to pick up its "current"
89+
value being changed afterwards. (Which is by design by React.)
90+
91+
To handle this case, you can do one of these three:
92+
93+
- Use the provided callback ref
94+
- Refactor to a component which you can mount after a "loading" concluded with
95+
the hook within it. This means that the hook will be mounted with the measured
96+
element, which means that a regular ref will work fine.
97+
- Use local state to store the custom ref the hook needs to observe, with "null"
98+
as its starting value. Then once loading concluded, set this state to the ref.
99+
This'll make the hook notice a change from null to the ref, where this time the
100+
ref actually has its current value set properly as well.
101+
([See example here](https://codesandbox.io/s/damp-cookies-6bdrg?file=/src/App.js))
102+
103+
Using a callback ref is recommended, and might look like this:
104+
105+
```tsx
106+
const { callbackRef, width, height } = useResizeObserver<HTMLDivElement>();
107+
const [loaded, setLoaded] = useState(false);
108+
109+
// Simulating a loading state.
110+
useEffect(() => {
111+
setTimeout(() => {
112+
setLoaded(true);
113+
}, 2000);
114+
}, []);
115+
116+
if (!loaded) {
117+
return <div>Loading...</div>;
118+
}
119+
120+
return <div ref={callbackRef}></div>;
121+
```
122+
123+
## Using a single hook to measure multiple refs
124+
125+
The hook reacts to ref changes, as it resolves it to an element to observe.
126+
This means that you can freely change the custom `ref` option from one ref to
127+
another and back, and the hook will start observing whatever is set in its options.
128+
129+
## Opting Out of (or Delaying) ResizeObserver instantiation
130+
131+
In certain cases you might want to delay creating a ResizeObserver instance.
132+
133+
You might provide a library, that only optionally provides observation features
134+
based on props, which means that while you have the hook within your component,
135+
you might not want to actually initialise it.
136+
137+
Another example is that you might want to entirely opt out of initialising, when
138+
you run some tests, where the environment does not provide the `ResizeObserver`.
139+
140+
([See discussions](https://github.com/ZeeCoder/use-resize-observer/issues/40))
141+
142+
You can do one of the following depending on your needs:
143+
144+
- Use a callback ref, or provide a custom ref conditionally, only when needed.
145+
The hook will not create a ResizeObserver instance up until there's something
146+
there to actually observe.
147+
- Patch the test environment, and make a polyfill available as the ResizeObserver.
148+
(This assumes you don't already use the polyfilled version, which would switch
149+
to the polyfill when no native implementation was available.)
150+
72151
## The "onResize" callback
73152

74153
By the default the hook will trigger a re-render on all changes to the target
@@ -78,13 +157,13 @@ You can opt out of this behaviour, by providing an `onResize` callback function,
78157
which'll simply receive the width and height of the element when it changes, so
79158
that you can decide what to do with it:
80159

81-
```js
160+
```tsx
82161
import React from "react";
83162
import useResizeObserver from "use-resize-observer";
84163

85164
const App = () => {
86165
// width / height will not be returned here when the onResize callback is present
87-
const { ref } = useResizeObserver({
166+
const { ref } = useResizeObserver<HTMLDivElement>({
88167
onResize: ({ width, height }) => {
89168
// do something here.
90169
},
@@ -119,8 +198,8 @@ and height by default.
119198

120199
You can override this behaviour, which could be useful for SSR as well.
121200

122-
```js
123-
const { ref, width = 100, height = 50 } = useResizeObserver();
201+
```ts
202+
const { ref, width = 100, height = 50 } = useResizeObserver<HTMLDivElement>();
124203
```
125204

126205
Here "width" and "height" will be 100 and 50 respectively, until the
@@ -131,8 +210,8 @@ ResizeObserver kicks in and reports the actual size.
131210
If you only want real measurements (only values from the ResizeObserver without
132211
any default values), then you can just leave defaults off:
133212

134-
```js
135-
const { ref, width, height } = useResizeObserver();
213+
```ts
214+
const { ref, width, height } = useResizeObserver<HTMLDivElement>();
136215
```
137216

138217
Here "width" and "height" will be undefined until the ResizeObserver takes its

docs/development.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Development
2+
3+
Various development notes.

karma.conf.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ module.exports = function (config) {
22
const browsers = (process.env.KARMA_BROWSERS || "ChromeHeadless").split(",");
33

44
const testFilePattern = "tests/*.tsx";
5+
// const testFilePattern = "tests/testing-lib.tsx";
56

67
config.set({
78
basePath: ".",

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "use-resize-observer",
3-
"version": "6.1.0",
3+
"version": "6.2.0-alpha1",
44
"main": "dist/bundle.cjs.js",
55
"module": "dist/bundle.esm.js",
66
"types": "dist/index.d.ts",
@@ -45,9 +45,10 @@
4545
"@babel/preset-env": "^7.7.7",
4646
"@babel/preset-react": "^7.9.4",
4747
"@babel/preset-typescript": "^7.9.0",
48+
"@rollup/plugin-babel": "^5.2.1",
4849
"@rollup/plugin-inject": "^4.0.1",
4950
"@size-limit/preset-small-lib": "^4.4.5",
50-
"@testing-library/react": "^10.0.2",
51+
"@testing-library/react": "^11.0.4",
5152
"@types/karma": "^5.0.0",
5253
"@types/karma-jasmine": "^3.1.0",
5354
"@types/react": "^16.9.34",
@@ -58,7 +59,7 @@
5859
"karma": "^5.0.1",
5960
"karma-chrome-launcher": "^3.0.0",
6061
"karma-firefox-launcher": "^1.3.0",
61-
"karma-jasmine": "^3.1.1",
62+
"karma-jasmine": "^4.0.1",
6263
"karma-sourcemap-loader": "^0.3.7",
6364
"karma-spec-reporter": "^0.0.32",
6465
"karma-webpack": "^4.0.2",
@@ -68,9 +69,8 @@
6869
"react": "^16.9.0",
6970
"react-dom": "^16.9.0",
7071
"rollup": "^2.6.1",
71-
"rollup-plugin-babel": "^4.4.0",
7272
"size-limit": "^4.4.5",
73-
"typescript": "^3.8.3"
73+
"typescript": "^4.0.3"
7474
},
7575
"dependencies": {
7676
"resize-observer-polyfill": "^1.5.1"

rollup.config.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
1-
import babel from "rollup-plugin-babel";
1+
import babel from "@rollup/plugin-babel";
22
import inject from "@rollup/plugin-inject";
33

44
const getConfig = ({ polyfill = false } = {}) => {
55
const config = {
66
input: "src/index.ts",
77
output: [],
8-
plugins: [babel({ extensions: ["ts"] })],
8+
plugins: [
9+
babel({
10+
extensions: ["ts"],
11+
// Seems like there's not really a difference in case of this lib, but
12+
// might worth reconsidering later to use "runtime".
13+
// @see https://github.com/rollup/plugins/tree/master/packages/babel#babelhelpers
14+
babelHelpers: "bundled",
15+
}),
16+
],
917
external: ["react"],
1018
};
1119

@@ -14,6 +22,7 @@ const getConfig = ({ polyfill = false } = {}) => {
1422
{
1523
file: "polyfilled.js",
1624
format: "cjs",
25+
exports: "default",
1726
},
1827
];
1928
config.external.push("resize-observer-polyfill");
@@ -27,6 +36,7 @@ const getConfig = ({ polyfill = false } = {}) => {
2736
{
2837
file: "dist/bundle.cjs.js",
2938
format: "cjs",
39+
exports: "default",
3040
},
3141
{
3242
file: "dist/bundle.esm.js",

0 commit comments

Comments
 (0)