rehooks / component-size Goto Github PK
View Code? Open in Web Editor NEWReact hook for determining the size of a component
License: MIT License
React hook for determining the size of a component
License: MIT License
Hi,
This follows the exact example: https://github.com/rehooks/component-size/blob/master/example.js exactly, and it breaks when there's a 100% height, (as per the example) or 100vh . Works if we set an exact height with px or em.
I understand it can be wrapped with a div. However, 100vh sets the height to 331px.
Using the example in the readme results in a 16x16 image.
https://codesandbox.io/s/ookwxx927y
Cheers
Reduced test case: https://stackblitz.com/edit/react-9vjncm
Here we are logging the size every time its reference changes. The actual size never actually changes.
As you can see, this results in 4 logs:
I would only expect the first two to be logged, since the last two are duplicates—the size has not changed.
This could result in wasted re-renders.
Title says it all. I'll be happy to send a PR!
Sizing through offsetWidth and offsetHeight results in rounded values instead of actual values, which leads to errors in Firefox.
Example, change the width of the results window to see the problem
Screenshots:
Links:
Demo: https://codesandbox.io/s/k06vw56xwo
The demo shows:
The physical span size is changing due to the content, but the size reported by the hook remains fixed (8 x 18 on my PC).
UPDATE:
After some more investigation, I think the issue is that ResizeObserver doesn't handle inline elements, just block elements. Simply changing the style of the span to display: inline-block
fixes this.
https://codesandbox.io/s/xv5vx3l01q
I created an element which changes the width of the div from 50vw to 100vw, but those changes only reflect on the resize of the window. Would be good if it can resize on change of the reference element
In index.js
, the hook falls back to using window.addEventListener('resize')
if ResizeObserver
is not available in the current browser. Therefore, it should be noted that you don't in fact require the polyfill to use this hook.
In my (Parcel+Babel) minified production output I'm getting errors that the let
statement is in there instead of var
. On investigation, it turns out to be only in @rehooks/component-size
. Of course this might be somehow context and config related, but I'm reporting it here as others might be running into this as well.
hi,@fouad thanks for the hook idea。
I have one question,when I use this hook,I found useLayoutEffect
will fire twice:
...
+ console.log('ref.current', ref.current)
handleResize()
then you will see the console below:
ref.current <div style="width: 50%; height: 50%;">…</div>
ref.current <div style="width: 50%; height: 50%;">…</div>
In my opinion,ref.current
is not changable,as the react doc said in will only fire once。
so THE QUESTION is:
why this will happen?
Hi,
When using useComponentSize
with server side rendering we experience this warning.
Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should only be used in components that render exclusively on the client. See https://fb.me/react-uselayouteffect-ssr for common fixes.%s
The warning points to this ressource https://fb.me/react-uselayouteffect-ssr for correct handling on the server.
This is not major but should be better for those of us using SSR 😉
Anyways, thanks for lib!
Would it potentially be better to allow someone to create their own ref and give it to you?
let myRef = useRef(null);
let size = useComponentSize(myRef);
That way they could pass it to multiple hooks
Thanks for the hook implementation.
A concern about disconnect method: MDN docs say that the disconnect
method doesn't receive any parameters, it rather disconnects all the connected observers.
A question about the constructor: I think the code creates a new constructor every time a new ref is given. Please correct me if I'm wrong, but given the fact that we always use the same handleResize
callback, shouldn't we use a single global ResizeObserver reference?
When resizing the component (eg. by resizing the window) for some time, the ResizeObserver spits out:
Error: ResizeObserver loop limit exceeded
Here's discussion and a potential solution for this issue:
https://stackoverflow.com/questions/49384120/resizeobserver-loop-limit-exceeded
offsetHeight
/offsetWidth
do not work with elements often in the DOM that are not actually HTML Elements, for example, SVG elements.
I'd recommend using clientHeight
/clientWidth
when the offset versions are undefined, but it could be considered a breaking change.
Another possibility would be to allow the passing of a callback to override getSize
.
for example:
import React, {useRef} from 'react';
import A from './A.jsx'
import useComponentSize from '@robooks/component-size';
function B(props) {
const ref = useRef();
const {width, height} = useComponentSize(ref);
return {width}:{height};
}
this work:
resizeObserver.observe(findDOMNode(ref.current));
thx
not working with React.forwardRef
I don't believe this code will work as expected:
Line 56 in c0abcb9
A change in a ref will not case a re-render, so there's no guarantee that this effect will be called. I'd suggest refactoring it to accept an empty array - it'll work the same.
The linked resize-observer-polyfill
package actually recommends using it as a ponyfill and has deprecated the polyfill behavior (leaving the name of the package questionable lol)
I believe this library should be able to take the ResizeObserver
instance as an optional argument.
Works fine on browser window resize and even in the Chrome Developer mobile preview however when viewing on a real iPad/iPhone the size doesn't change when the iOS device is rotated.
I believe this doesn't trigger a resize but instead an orientationchange event which should be listened for.
I've tried with resize-observer-polyfill and still the same outcome.
Not sure if this is a component-size issue or a ResizeObserver issue (or if i'm just doing something wrong)
edit:
Looks like it possibly my issue. However i'm still seeing the following when i print the size to the screen:
Initial View in Portrait Mode:
{"width":722, "height":1058}
Rotate iPad to Landscape
{"width":722, "height":1058} // No change
Rotate iPad Back to Portrait
{"width":1082, "height": 698} // Changed but referring to the old landscape size
So it looks like it's missing the orientationchange event on the iOS device. Again works fine in the Chrome Browser.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.