ZeeCoder / use-resize-observer

A React hook that allows you to use a ResizeObserver to measure an element's size.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support getBoundingClientRect()

ivanjeremic opened this issue · comments

The returned width and height should also be also available as what we get from el.getBoundingClientRect().width & el.getBoundingClientRect().height sometimes we need exact sitze and i didn't see anything in the Readme that this library supports that already, please correct me if I'm wrong.

Not sure what you mean by "exact size". ResizeObservers support some box options now, maybe that's what you need?

This library is intentionally resisting such feature and aims to be thin hook to use ResizeObserver as-is,
so this will definitely not be supported out of the box.

Features like these can be implemented in composing hooks easily: see throttle / debounce and breakpoint examples in the readme.

Also, getBoundingClientRect is one of the calls you can make in JS land that causes layout trashing, avoiding which is one of the main selling points of using the native ResizeObserver.

What I could do, however, is giving easy access to the observed element in the onResize callback, so that you can compose the hook and add this feature yourself.

Pseudo-code:

const useBoundingClientRect = () => {
  const [size, setSize] = useState({ width: undefined, height: undefined });
  const { ref } = useResizeObserver({
    onResize: useMemo(({ element }) => {
      const { width, height } = element.getBoundingClientRect(); // This trashes the layout
      setSize({ width, height });
    }),
  });

  return { ...size, ref };
};

I would probably combine this with throttling, to lessen the effects of layout trashing.

This is already possible btw, you just don't have such an easy access to the element rn.

Not sure what you mean by "exact size". ResizeObservers support some box options now, maybe that's what you need?

Thanks, I was thinking maybe this library will go in the direction like Solid.js primitive https://www.npmjs.com/package/@solid-primitives/resize-observer but totally ok if not, this is now solved for me and can be closed. Thanks

I can't see any instances of that lib using getBoundingClientRect either.

I can't see any instances of that lib using getBoundingClientRect either.

I know but it goes in a direction where it is very likely they will.

Got it 👍

@ZeeCoder I tried your snippet but that didn't work. You closed this issue as completed, but I think I missed the change related to this. How can I obtain the element?

It was closed, nothing was done, that snippet was only a potential implementation.
You should have access to the element already though, as you'd need to pass it in either as a ref object or call the callback ref with it.

I'd advise against using getBoundingClientRect though, and use the box option instead if possible.

I'd advise against using getBoundingClientRect though, and use the box option instead if possible.

I understand the concerns but some information can only be obtained from getBoundingClientRect as it returns more than width and height. I read somewhere, I think, that you don't want to return more than just those two attributes regardless of what's available, right?

You should have access to the element already though, as you'd need to pass it in either as a ref object or call the callback ref with it.

👍 that's fine, just wondering if that was available and I was missing something. I tried both merging ref or passing in a ref and both worked to get the element. 👍

@bpinto to be precise I won't return anything that's not what ResizeObserver gives you, which currently only width/height.
If I used getBoundingClientRect to return more things it would A) go against the philosophy of this hook being minimal to be as composable as possible (feature creep), and B) it would mean that you lose the benefit of ResizeObserver reporting size changes before layout / paint.

Getting the element through onResize does not go against either of those though, and I can see implementing something like this being a bit of a pain, so I'll change this issue to a discussion instead.
Could be part of a future minor release.