Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

All dimensions returned as 0 #29

Open
dfsa-bot opened this issue Mar 4, 2020 · 1 comment
Open

All dimensions returned as 0 #29

dfsa-bot opened this issue Mar 4, 2020 · 1 comment

Comments

@dfsa-bot
Copy link

dfsa-bot commented Mar 4, 2020

Hey,
I'm kind of stuck with all dimensions being 0 on first Component render. Hot-reloading somehow magically sets the values to correct ones but that obviously won't do.
Nothing fancy here:

const [itemRef, { x }, node] = useDimensions()

useEffect(() => {
  console.log(x)
}, [x])

...
return (
  <Component ref={itemRef}>
    {children}
  </Component>
)
...

Actually the first render gets me all 'undefined' (including node), the second one comes back with 0s and node as actual HTMLElement.

Any ideas what might be the cause of this? The container element is a flex-box wrapper - I thought this might be it but then tried to run useDimensions on that element and same results came back

@dfsa-bot dfsa-bot reopened this Mar 17, 2020
@furkankly
Copy link

I don't know the actual reason behind this but as I was trying to debug this problem, I've realized even though the getDimensionObject receives the correct node each time it's called, getBoundingClientRect call in it, returns 0 values for the initial render just like you mentioned.

The measure function
const measure = () => window.requestAnimationFrame(() => setDimensions(getDimensionObject(node))); in useLayoutEffect is where we set the dimensions state and I wanted to make sure node state is up to date before calling the getDimensionObject as i mentioned above.

It's not recommended to store the ref (the actual node) in a state as setState (setNode in our case) is async. So what is the proper way to store the actual node in callback refs rather than a state? I don't know, maybe just using a regular ref instantiated by useRef with its .current so we can do nodeRef.current = node in our callback ref instead of doing setNode.

But whole point of using callback refs is to have more control over the refs we create, so we actually make these refs our part of the data flow by using useCallback hook as the regular refs can go deep down and we can't have them as our hook dependencies. (they don't even trigger re-renders as they are mutable.) So using regular refs to store the actual nodes while using callback refs feel so wrong in so many ways and I stick with a state to store them just like in this library.

At this point, I just wanted to make sure I'm getting the dimensions of the "final version" of the node in the initial render so I wanted to give some time to async setState to settle down by putting a timeout on requestAnimationFrame just like:

const measure = () => window.requestAnimationFrame(() => setTimeout(() => setDimensions(getDimensionObject(node)), 100) );

and it worked. (Not to mention about the performance but this addition feels quite hacky...)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants