jaredLunde/react-hook

The useSize() demo for resize-observer doesn't capture element's initial size

jdthorpe opened this issue · 1 comments

Describe the bug
The useSize() function in the demo for @react-hook/resize-observer uses the anti-pattern of depending on the ref object provided by React.useRef() in the dependency list of React.useLayoutEffect(). This has the effect of not setting an initial value for the size on the first rendering. This matters because elements that don't get re-rendered never get a sized.

To Reproduce
Use the size

Expected behavior
Get a size for elements on the first time they are rendered.

Additional context
Depending on the node itself via useState instead of the ref (which is never updated and therefor never calls) is the usual work around

export function useSize(): {
    ref: (node: HTMLDivElement | null) => void
    size: DOMRect | undefined
} {
    const [size, setSize] = useState<DOMRect | undefined>()
    const [node, ref] = useState<HTMLElement | null>(null)

    useLayoutEffect(() => {
        node !== null && setSize(node.getBoundingClientRect())
    }, [node])

    // Where the magic happens
    useResizeObserver(node, (entry) => {
        setSize(entry.contentRect)
    })

    return { ref, size } // this is also a little wierd since ref isn't a ref object but a setter function, but works if using it in the context of <div ref={ref}>
}

https://codesandbox.io/s/react-hookresize-observer-example-ft88x?file=/src/App.js

Fixed in the demo but feel free to submit a PR for the README :) Thanks!