Description
At the time React added callback refs the main use case for them was to replace string refs. A lot of the callback refs looked like this:
<div ref={node => this.node = node} />
With the introduction of createRef
and useRef
this use case is pretty much replaced by these alternatives so the use case of callback refs will shift to advanced use cases like measuring DOM nodes.
It would be nice if you could return a cleanup function from the callback ref which is called instead of the callback with null. This way it will behave more like the useEffect
API.
<div ref={node => {
// Normal ref callback
return () => {
// Cleanup function which is called when the ref is removed
}
}} />
This will be super helpful when you need to set up a Resize-, Intersection- or MutationObserver.
function useDimensions() {
const [entry, setEntry] = useState()
const targetRef = useCallback((node) => {
const observer = new ResizeObserver(([entry]) => {
setEntry(entry)
})
observer.observe(node)
return () => {
observer.disconnect()
}
}, [])
return [entry, targetRef]
}
function Comp() {
const [dimensions, targetRef] = useDimensions()
return (
<pre ref={targetRef}>
{JSON.stringify(dimensions, null, 2)}
</pre>
)
}
Currently, if you want to implement something like this you need to save the observer into a ref and then if the callback ref is called with null you have to clean up the observer from the ref.
To be 99% backward compatible we could call both the callback ref with null and the cleanup function. The only case where it isn't backward compatible is if currently someone is returning a function and doesn't expect the function to be called.
function ref(node) {
if (node === null) {
return
}
// Do something
return () => {
// Cleanup something
}
}