@@ -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
4042Note that the default builds are not polyfilled! For instructions and alternatives,
4143see the [ Transpilation / Polyfilling] ( #transpilation--polyfilling ) section.
4244
43- ``` js
45+ ``` tsx
4446import React from " react" ;
4547import useResizeObserver from " use-resize-observer" ;
4648
4749const 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 = () => {
6062You can pass in your own ref instead of using the one provided.
6163This 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
6870You 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
74153By 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,
78157which'll simply receive the width and height of the element when it changes, so
79158that you can decide what to do with it:
80159
81- ``` js
160+ ``` tsx
82161import React from " react" ;
83162import useResizeObserver from " use-resize-observer" ;
84163
85164const 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
120199You 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
126205Here "width" and "height" will be 100 and 50 respectively, until the
@@ -131,8 +210,8 @@ ResizeObserver kicks in and reports the actual size.
131210If you only want real measurements (only values from the ResizeObserver without
132211any 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
138217Here "width" and "height" will be undefined until the ResizeObserver takes its
0 commit comments