React 커스텀 훅 : 컴포넌트의 크기(사이즈)를 가져오는 훅

hwisaac·2023년 2월 23일
2

커스텀훅

목록 보기
1/3

다른 컴포넌트에서 쉽게 해당 컴포넌트의 크기를 가져오는 훅입니다.

코드

import { useState, useEffect, useRef } from 'react';

interface ComponentSize {
  width: number;
  height: number;
};

function useComponentSize(): [React.RefObject<HTMLDivElement>, ComponentSize] {
  const [size, setSize] = useState<ComponentSize>({ width: 0, height: 0 });
  const componentRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const handleResize = () => {
      const { width, height } = componentRef.current?.getBoundingClientRect() ?? { width: 0, height: 0 };
      setSize({ width, height });
    };

    handleResize();

    window.addEventListener('resize', handleResize);

    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return [componentRef, size];
}

export default useComponentSize;
  1. 위 코드에서는 ComponentSize라는 인터페이스를 정의하여 컴포넌트의 가로 너비와 세로 너비를 표현합니다. 이 인터페이스를 사용하여 size 상태를 정의하고 초기값을 { width: 0, height: 0 }로 설정합니다.

  2. useRef 훅을 사용하여 컴포넌트의 DOM 요소에 대한 참조를 생성하고, useEffect 훅을 사용하여 이벤트 리스너를 등록합니다. 이벤트가 발생하면 handleResize 함수가 호출되고, 이 함수에서 getBoundingClientRect 메서드를 사용하여 컴포넌트의 가로 너비와 세로 너비를 가져옵니다.

  3. handleResize 함수에서 가져온 크기 정보는 setSize 함수를 사용하여 size 상태를 업데이트합니다.

  4. 마지막으로, useComponentSize 훅은 [componentRef, size] 튜플을 반환합니다. 이 튜플은 ref와 크기 정보를 포함하고 있습니다.

사용예시

이렇게 사용하면 다른 컴포넌트에서 해당 컴포넌트의 크기를 가져올 수 있습니다.

import React, { useRef } from 'react';
import useComponentSize from './useComponentSize';

function MyComponent() {
  const [componentRef, size] = useComponentSize();

  return (
    <div ref={componentRef}>
      <p>가로너비: {size.width}px</p>
      <p>세로너비: {size.height}px</p>
    </div>
  );
}

1개의 댓글

comment-user-thumbnail
2024년 1월 31일

올려주신 좋은 글 잘 읽었습니다. 덕분에 문제 해결이 되었습니다.
오지랖이겠지만 조금 추가해보았습니다.

사용하는 곳에서 ref를 만들어서 커스텀 훅의 인자로 넘겨주는 방식으로 바꾸어보았어요.

// useComponentSize.ts
import { useState, useEffect, RefObject } from 'react';

interface ComponentSize {
  width: number;
  height: number;
}

function useComponentSize<T extends HTMLElement>(
  externalRef: RefObject<T>,
): [RefObject<T>, ComponentSize] {
  const [size, setSize] = useState<ComponentSize>({ width: 0, height: 0 });
  const componentRef = externalRef;

  useEffect(() => {
    const handleResize = () => {
      const { width, height } =
        componentRef.current?.getBoundingClientRect() ?? {
          width: 0,
          height: 0,
        };
      setSize({ width, height });
    };

    handleResize();

    window.addEventListener('resize', handleResize);

    return () => window.removeEventListener('resize', handleResize);
  }, [externalRef]);

  return [componentRef, size];
}

export default useComponentSize;
// 사용하는 곳
  const tableRef = useRef<HTMLTableElement>(null);
  const [componentRef, size] = useComponentSize<HTMLTableElement>(tableRef);
답글 달기