React => measuring a DOM node
Your first instinct will be to use a useRef
which can be a good solution, although an object ref doesn’t notify us about changes to the current ref value. This means when the ref.current
changes you will not see the updated value.
Use a callback ref (this example is taken from the react hooks FAQ) This is a super simple and pretty nice solution for one-off measurements.
function MeasureExample() {
const [height, setHeight] = useState(0);
const measuredRef = useCallback(node => {
if (node !== null) {
setHeight(node.getBoundingClientRect().height);
}}, []);
return (
<>
<h1 ref={measuredRef}>Hello world</h1>
<h2>The above header is {Math.round(height)}px tall</h2>
</>
);
}
This solution is a pretty elegant fix for this problem while keeping the integrity/behaviour .current
of a traditional ref.
import React from 'react'
function useRefCallback() {
const ref = React.useRef(null)
const setRef = React.useCallback(node => {
if (ref.current) {
// Make sure to cleanup any events/references
// Ref.current at this point will be the preview instanct
}
if (node) {
// Check if a node is passed. Otherwise, node would be null.
// You can now do what you need to, addEventListeners, measure, etc.
}
// Save a reference to the node
ref.current = node
}, [])
return [ref, setRef]
}
function App() {
const [setRef] = useRefCallback()
return <div ref={setRef}>Ref element</div>
}