큰 꿈은 파편이 크다!!⚡️

예제로 이해하는 React Custom Hook 본문

Web FE

예제로 이해하는 React Custom Hook

wood.forest 2022. 6. 25. 18:28
Building your own Hooks lets you extract component logic into reusable functions.

 

 

useState, useEffect, useMemo 등의 훅Hook은 리액트 16.8버전부터 추가되어 클래스를 작성하지 않고도 상태State관리를 편하게 할 수 있는 혁신적인 기능이었다. 

그리고 재미있게도 나만의 커스텀 훅을 만드는 기능도 제공된다. 리액트 팀에서 훅을 만드는 원리대로 내 것을 만들 수 있다.

훅 또한 컴포넌트 등과 마찬가지로 함수이기 때문에 자바스크립트에서 함수를 분리할 때와 같이 분리하고, 컴포넌트에서 사용하고 싶은 값을 반환한다. 많이 사용되는 커스텀 예제들을 통해 어떤 식으로 사용할 수 있는지 알아보고, 익숙해져 보자!

 

🧐 고려할 것

· 재사용을 위해 분리한 함수이므로 unconditional 해야 한다

· use로 시작하는 컨벤션을 따른다

· 내부에서는 useState 등을 사용해서 자유롭게 만든다

 

 

예시.  useWindowSize

브라우저 창 크기가 바뀔 때를 감지하여 사용할 수 있는 useWindowSize 커스텀 훅이다.

 

1. useState를 사용해서 window의 width, height를 관리한다

2. 최초 mount되었을 때 "resize" 이벤트 리스너를 추가한다. resize이벤트가 발생할때마다, useState로 설정한 window객체의 값을 갱신한다.

3. unmount될 때 resize이벤트를 제거한다.

export const useWindowSize = () => {
  // Initialize state with undefined width/height so server and client renders match
  // Learn more here: https://joshwcomeau.com/react/the-perils-of-rehydration/
  const [windowSize, setWindowSize] = useState({
    width: undefined,
    height: undefined,
  });
  useEffect(() => {
    // Handler to call on window resize
    function handleResize() {
      // Set window width/height to state
      setWindowSize({
        width: window.innerWidth,
        height: window.innerHeight,
      });
    }
    // Add event listener
    window.addEventListener("resize", handleResize);
    // Call handler right away so state gets updated with initial window size
    handleResize();
    // Remove event listener on cleanup
    return () => window.removeEventListener("resize", handleResize);
  }, []); // Empty array ensures that effect is only run on mount
  return windowSize;
};

 

 

 

예시. useScroll

X, 또는 Y방향으로 Scroll 이벤트가 발생할때마다 Body Offset의 X, Y position을 나타내는데, scroll 이벤트이니만큼 debounce 등을 추가해서 더 효율적으로 개선할 수 있다.

코드의 흐름을 보면 위 useWindow 와 거의 동일함을 알 수 있다.

 

1. 필요한 변수들을 useState로 선언한다.

2. 최초 mount되었을 때 "scroll" 이벤트 리스너를 추가한다. scroll 이벤트가 발생할때마다, useState로 설정한 객체의 값을 갱신한다.

3. unmount될 때 scroll이벤트를 제거한다.

import { useState, useEffect } from "react";

export function useScroll() {
  const [lastScrollTop, setLastScrollTop] = useState(0);
  const [bodyOffset, setBodyOffset] = useState(
    document.body.getBoundingClientRect()
  );
  const [scrollY, setScrollY] = useState(bodyOffset.top);
  const [scrollX, setScrollX] = useState(bodyOffset.left);
  const [scrollDirection, setScrollDirection] = useState();

  const listener = e => {
    setBodyOffset(document.body.getBoundingClientRect());
    setScrollY(-bodyOffset.top);
    setScrollX(bodyOffset.left);
    setScrollDirection(lastScrollTop > -bodyOffset.top ? "down" : "up");
    setLastScrollTop(-bodyOffset.top);
  };

  useEffect(() => {
    window.addEventListener("scroll", listener);
    return () => {
      window.removeEventListener("scroll", listener);
    };
  });

  return {
    scrollY,
    scrollX,
    scrollDirection
  };
}

 

 

 

사용

예시의 두 훅은 이렇게 사용한다.

☝️ 커스텀 훅을 통해서 인터랙티브한 페이지에서 자주 사용될 수 있는 이벤트들을 재사용하고,

✌️ 파일의 코드 라인 수도 줄일 수 있다.

 

 

· 브라우저 창 크기를 조절하면 변경된 크기의 width, height를 나타낸다.

· 스크롤 시 position을 나타낸다.

 

 

 

 

마무리

Custom Hook에 대해 정확하게 몰라서 기술부채라고 생각하고, 이번 글을 통해 다루어보았는데.. 생각보다 다룰 것이 없는 만큼 간단한 내용인 걸 알았다. 괜히 커스텀이라고 하니까 어려울 것이라 지레짐작하고 제대로 보지 않았던 나를 반성한다.🫥

원리를 아는 것과 응용은 별개의 문제겠지만 이제는 몰라서 안쓰는 게 아닌, 쓸 상황을 알고 사용 유무를 결정하겠다!

 

 

 

 

Reference

- https://reactjs.org/docs/hooks-custom.html

- https://react.vlpt.us/basic/21-custom-hook.html

- https://gist.github.com/joshuacerbito/ea318a6a7ca4336e9fadb9ae5bbb87f4

반응형