React와 함께 Resize Observer를 사용하는 방법

Web API 시리즈의 첫 번째 부분에서 우리는 Resize Observer API가 무엇이고 바닐라 JavaScript와 함께 사용하는 방법을 배웠습니다. 하지만 React와 함께 사용하려면 어떻게 해야 할까요?
오늘 우리는 이를 빠르고 쉽게 수행하는 방법을 살펴보고 프로젝트에서 사용할 수 있는 사용자 지정 후크를 만들 것입니다.

API



우리가 이미 알고 있는 것을 반복해 봅시다.

  • ResizeObserver는 요소 크기의 변경 사항을 관찰하는 데 사용됩니다
  • .
  • 자체 관찰자 인스턴스를 생성하기 위해 크기가 변경될 때마다 실행되는 콜백 함수를 전달하는 ResizeObserver 생성자를 호출합니다.

  • const myObserver = new ResizeObserver(
      (entries: ResizeObserverEntry[], observer: ResizeObserver) => {
        for (let entry of entries) {
          // Do something with an entry (see in next section)
        }
    });
    

  • 요소의 크기 감시를 시작/중지하려면 observe/unobserve 인스턴스의 메서드를 호출해야 합니다.

  • const myElement = document.getElementById('my-element');
    myObserver.observe(myElement); // Start watching
    myObserver.unobserve(myElement); // Stop watching
    

  • 관찰된 각 항목에는 항목의 요소 크기 정보가 포함되어 있습니다.

  • interface ResizeObserverEntry {
      readonly target: Element;
      readonly borderBoxSize: ReadonlyArray<ResizeObserverSize>;
      readonly contentBoxSize: ReadonlyArray<ResizeObserverSize>;
      readonly devicePixelContentBoxSize: ReadonlyArray<ResizeObserverSize>;
      readonly contentRect: DOMRectReadOnly; // May be deprecated, don't use it!
    }
    
    interface ResizeObserverSize {
        readonly blockSize: number;
        readonly inlineSize: number;
    }
    

    작업



    다음으로 우리는 지식을 사용하여 모든 React 앱에서 크기를 얻고 싶습니다. 모든 구성 요소의 모든 프로젝트에서 사용할 수 있는 React Hook을 만드는 것보다 더 나은 솔루션은 없습니다.
    이제 후크에서 정확히 원하는 것을 정의해 보겠습니다.
  • 보편적이어야 하며 사용법은 const size = giveMeMySize() 처럼 간단해야 합니다.
  • 아마도 이전 섹션에서 보았듯이(희망합니다 😄) 하나의ResizeObserver 인스턴스는 모든 요소를 ​​처리할 수 있습니다. 앱 성능을 유지하려면 후크가 내부에 있는 단일 관찰자 인스턴스만 사용해야 합니다.
  • 후크를 사용하기 편리하게 만들려면 돌연변이 자체를 처리하고 마운트 해제 시 관찰을 자동으로 중지해야 합니다.
  • ResizeObserver API는 이미 광범위하게 지원되지만 여전히 Editor's Draft에 있으며 모든 브라우저에서 지원되지는 않습니다. 대비책을 제공하는 것이 좋습니다.

  • 해결책



    우리의 요구 사항은 좋아 보이고 꽤 엄격해 보이죠? 하지만 걱정하지 마세요. Jared Lunde의 아름다운react-hook 라이브러리에서 아름답고 매우 사용하기 쉬운useResizeObserver 후크를 사용하여 모든 문제를 처리할 수 있습니다. 그것documentation과 나의 테스트 및 사용법에 따르면 그것은 우리의 모든 요구 사항을 충족합니다.

    • Uses a single ResizeObserver for tracking all elements used by the hooks. This approach is astoundingly more performant than using a ResizeObserver per element which most hook implementations do,
    • Uses @juggle/resize-observer as a ponyfill when ResizeObserver isn't supported by the current browser,
    • automatically unobserves the target element when the hook unmounts,
    • you don't have to wrap your callback in useCallback() because any mutations are handled by the hook.


    유망한 느낌, 지금 바로 사용하지 않겠습니까?

    후크



    드디어 후크를 만들 준비가 되었습니다. 먼저 useResizeObserver 후크를 설치합니다.

    npm install @react-hook/resize-observer
    // Or
    yarn install @react-hook/resize-observer
    


    그런 다음 후크가 어떻게 생겼는지 정의해 보겠습니다.

    // useElementSize.ts
    import { MutableRefObject, useLayoutEffect, useRef, useState } from 'react';
    import useResizeObserver from '@react-hook/resize-observer';
    
    interface Size {
      width: number;
      height: number;
    }
    
    export default function useElementSize<T extends HTMLElement = HTMLDivElement>(): [MutableRefObject<T | null>, Size] {
      const target = useRef<T | null>(null);
      const [size, setSize] = useState<Size>({
        width: 0,
        height: 0,
      });
    
      return [target, size]
    }
    


    보다시피 우리는 요소의 일반 유형을 제공할 수 있는 useElementSize 함수를 만들었습니다. 구성 요소 내부의 React 요소에 연결하기 위한 target 참조와 size 인터페이스를 구현하는 현재 요소의 크기 상태에 대한 Size 참조를 생성합니다.

    요소의 크기를 조정하는 동안 크기는 십진수일 수 있으며 일반적으로 그렇습니다. 물론 반올림할 수 있습니다.

    const setRoundedSize = ({ width, height }: Size) => {
      setSize({ width: Math.round(width), height: Math.round(height) });
    };
    


    다음으로 요소의 이니셜size을 설정해야 합니다. 이것은 ReactuseLayoutEffect 후크가 완벽하게 맞는 곳입니다. 브라우저 페인트 전에 실행되어 getBoundingClientRect 메서드를 사용하여 요소의 크기를 가져올 수 있습니다.

    useLayoutEffect(() => {
        target.current && setRoundedSize(target.current.getBoundingClientRect())
    }, [target]);
    


    그리고 마지막으로 useResizeObserver 후크의 도움을 받아 대상의 크기가 변경될 때마다 size 업데이트를 트리거하는 마법(not)을 적용해 보겠습니다.

    useResizeObserver(target, entry => {
      const { inlineSize: width, blockSize: height } = entry.contentBoxSize[0];
      setRoundedSize({ width, height });
    });
    


    그리고 사용법🤠



    시리즈의 첫 번째 부분에서 연습을 반복해 봅시다. 작업을 상기시켜 드리겠습니다.

    Say we have a box of strawberries and getting them bigger makes us really happy (and vice versa).



    자세한 설명은 하지 않겠습니다. 아시다시피 우리의 목표는 사용하기 매우 쉬운 후크를 만드는 것이었기 때문입니다. 아래에서 코드와 작동 방식을 모두 확인할 수 있습니다.
    어떻게 된 것 같나요?




    이 가이드가 마음에 드셨기를 바라며 계속 지켜봐 주시기 바랍니다.

    좋은 웹페이지 즐겨찾기