Advertisement
Guest User

Untitled

a guest
Jun 26th, 2019
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.29 KB | None | 0 0
  1. import { useCallback, useLayoutEffect, useState, useRef } from 'react'
  2.  
  3. /**
  4. * Returns the bounding client rect of a HTML element, uses the `ResizeObserver` api if available to detect changes to the
  5. * size. Falls back to listening for resize events on the window.
  6. */
  7. export function useBoundingRect<T extends HTMLElement>(): [React.Ref<T>, ClientRect | DOMRect] {
  8. const ref = useRef<T>()
  9. const [rect, setRect] = useState()
  10.  
  11. const recalculator = useCallback(() => {
  12. if (ref.current) {
  13. setRect(ref.current.getBoundingClientRect())
  14. }
  15. }, [ref])
  16.  
  17. // Handle changing of size
  18. useLayoutEffect(() => {
  19. const { ResizeObserver } = window
  20.  
  21. if (!ref.current) return
  22. recalculator()
  23.  
  24. window.addEventListener('resize', recalculator)
  25.  
  26. let resizeObserver: ResizeObserver
  27. if (typeof ResizeObserver === 'function') {
  28. resizeObserver = new ResizeObserver(recalculator)
  29. resizeObserver.observe(ref.current)
  30. }
  31.  
  32. return () => {
  33. window.removeEventListener('resize', recalculator)
  34. if (resizeObserver) resizeObserver.disconnect()
  35. }
  36. }, [ref, recalculator])
  37.  
  38. // Handle document scroll
  39. useLayoutEffect(() => {
  40. document.addEventListener('scroll', recalculator)
  41. return () => document.removeEventListener('scroll', recalculator)
  42. })
  43.  
  44. return [ref, rect]
  45. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement