All files / src/hooks useSize.ts

0% Statements 0/14
0% Branches 0/4
0% Functions 0/5
0% Lines 0/13

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45                                                                                         
// NOTE: same as in uniprot-website codebase
import { type MutableRefObject, useCallback, useEffect, useState } from 'react';
 
/**
 * given a reference to an actual HTML element, gives us access to its size
 * even through resizes and zoom
 * @param {MutableRefObject<HTMLElement>} ref
 * @returns {Array} tuple - return tuple
 * @returns {DOMRect | null} tuple[0]
 *          DOMRect object with the sizes of the passed ref, or null if no ref
 * @returns {() => void} tuple[1]
 *          Manual refresh function, to call if the size needs to be recomputed
 *          for whatever reason (e.g. content changed)
 */
function useSize(
  ref: MutableRefObject<Element | null>
): [rect: DOMRect | undefined, onResize: () => void] {
  const [rect, setRect] = useState<DOMRect>();
 
  const onResize = useCallback(() => {
    if (!ref.current) {
      return;
    }
    setRect(ref.current.getBoundingClientRect());
  }, [ref, setRect]);
 
  // This effect will run after EVERY render
  useEffect(() => {
    // ask for size value until we finally get one
    if (!rect) {
      onResize();
    }
  }); // No dependency array, it's on purpose!
 
  useEffect(() => {
    onResize(); // first time
    window.addEventListener('resize', onResize);
    return () => window.removeEventListener('resize', onResize);
  }, [ref, onResize]);
 
  return [rect, onResize];
}
 
export default useSize;