Created
November 22, 2019 20:25
-
-
Save souporserious/76a0655cdd148eeddfdfb337f5d4fba7 to your computer and use it in GitHub Desktop.
react-measure v4 iteration
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export function useMeasure( | |
measureRef, | |
getDimensions = getRect, | |
shouldUpdate = (prev, next) => !shallowEqual(prev, next) | |
) { | |
const [dimensions, setDimensions] = useState( | |
getDimensions(measureRef.current) | |
) | |
const mutationObserver = useRef(null) | |
const resizeObserver = useRef(null) | |
const animationId = useRef(null) | |
const measure = () => { | |
if (animationId.current === null) { | |
animationId.current = window.requestAnimationFrame(() => { | |
setDimensions(dimensions => { | |
const nextDimensions = getDimensions(measureRef.current) | |
if (shouldUpdate(dimensions, nextDimensions)) { | |
return nextDimensions | |
} else { | |
return dimensions | |
} | |
}) | |
animationId.current = null | |
}) | |
} | |
} | |
if (typeof window !== 'undefined') { | |
if (!mutationObserver.current) { | |
mutationObserver.current = new MutationObserver(measure) | |
} | |
if (!resizeObserver.current) { | |
resizeObserver.current = new ResizeObserver(measure) | |
} | |
useLayoutEffect(() => { | |
setDimensions(getDimensions(measureRef.current)) | |
}, []) | |
} | |
useEffect(() => { | |
if (mutationObserver.current) { | |
mutationObserver.current.observe(measureRef.current, { | |
characterData: true, | |
childList: true, | |
subtree: true, | |
}) | |
} | |
if (resizeObserver.current) { | |
resizeObserver.current.observe(measureRef.current) | |
} | |
return () => { | |
if (mutationObserver.current) { | |
mutationObserver.current.disconnect() | |
} | |
if (resizeObserver.current) { | |
resizeObserver.current.disconnect() | |
} | |
if (animationId.current) { | |
window.cancelAnimationFrame(animationId.current) | |
} | |
} | |
}, []) | |
return dimensions | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Looks awesome. I often find it necessary to return a callback ref for components like these where you can't determine if the ref is present upon mount. I.e,:
It's not as elegant as accepting a ref as an argument to the hook though. But I don't see much of an alternative.