useDimensions
useDimensions copied to clipboard
Ability to listen for scroller other than document
I tried this library, and hit a use case where the scroll listener needed to be added to a scrollable element inside some other elements. My solution looks something like this:
import { useEffect, useLayoutEffect, useCallback } from 'react';
// Inspired by https://github.com/Swizec/useDimensions
export const useDimensions = ({ wrapperRef, scrollerRef, setDomRect }) => {
// Measures the current dimensions.
const measure = useCallback(() => {
setDomRect(wrapperRef.current.getBoundingClientRect());
}, [wrapperRef, setDomRect]);
// Handles the case that the first measure causes a vertical
// scrollbar to be introduced, which throws off the transform.
// requestAnimationFrame effectively waits for the scrollbar to appear.
const measureTwice = useCallback(() => {
measure();
requestAnimationFrame(measure);
}, [measure]);
// Measure the initial dimensions.
useLayoutEffect(measureTwice, [measure]);
// Measure the dimensions on resize.
useEffect(() => {
window.addEventListener('resize', measureTwice);
return () => {
window.removeEventListener('resize', measureTwice);
};
}, [measureTwice, scrollerRef]);
// Measure the dimensions on scroll.
useEffect(() => {
if (scrollerRef) {
const scroller = scrollerRef.current;
scroller.addEventListener('scroll', measure);
return () => {
scroller.removeEventListener('scroll', measure);
};
}
}, [measure, scrollerRef]);
};
I saw that the current code uses callback-style refs, apparently at the behest of Dan Abramov. I thought they were being phased out, so I don't know why that is.
In any case, what if you want to measure document scroll anyway? How to yet get a ref to that? Wouldn't it be better to pass the actual element somehow?
Also, how does the getBoundingClientRect introduce a scrollbar? I can't find anything on that…