Custom Hook

학습 키워드

  • Custom Hook

    • Hook의 규칙

  • usehooks-ts

    • useBoolean

    • useCounter

    • useEffectOnce

    • useFetch

      • SWR

      • React-Query

    • useInterval

    • useEventListener

    • useLocalStorage

    • useDarkMode

  • 컴포넌트 로직을 함수로 뽑아내어 재사용할 수 있는 방법

  • React의 State와 Lifecycle 관리 로직을 공통화 할 수 있도록 도와주는 역활 (컴포넌트간의 로직 공유)

🤖 Custom hook 사용법

  • use로 시작해야 하고 PascalCase로 이름을 생성한다.

  • 📁 hooks폴더를 생성하고 하나의 파일로 분리 후 사용

📌 Hook의 규칙

1. 최상위(at the Top Level)에서만 Hook을 호출해야 한다

  • 반복문, 조건문 혹은 중첩된 함수 내에서 Hook을 호출하지 않는다.

// 처음에는 콜백 함수나 조건문 안에서 Hook을 호출하는 실수를 하게 된다.
// Bad!!
if (playing) {
 const products = useFetchProducts();
 console.log(products);
}

2. React 함수 내에서 Hook을 호출해야 한다

  • React 함수 컴포넌트에서 Hook을 호출

  • Custom Hook에서 Hook을 호출

📖 usehooks-ts란?

  • Hook 라이브러리

  • Hook을 어떻게 만들었는지 코드를 볼 수 있고 Custom Hook을 만드는데 영감을 얻을 수 있다.

usehooks-ts 설치

npm i usehooks-ts

⚙️ useBoolean

  • 참/거짓을 다룰 땐 toggle 같이 의도가 명확한 함수를 쓰는 게 좋다.

import { useState } from 'react';
import { useBoolean } from 'usehooks-ts';

export default function Toggle() {

  const [stateToggle, setStateToggle] = useState(false);
  const { value: myToggle, toggle: myToggleFun } = useBoolean(false); 
  // setStateToggle(!stateToggle) 보다 toggle 혹은 myToggleFun이 의도가 명확하다.

  const handleState = () => {
    setStateToggle(!stateToggle); 
  };

  return (
    <div>
      <p> useState : {stateToggle ? 'True' : 'False'}</p>
      <p> useBoolean : {myToggle ? 'True' : 'False'}</p>
      <button type="button" onClick={handleState}>
        useState hook 토글 버튼
      </button>
      <button type="button" onClick={myToggleFun}>
        useBoolean hook 토글 버튼
      </button>
    </div>
  );
}

⚙️ useCounter

import { useCounter } from 'usehooks-ts'; // 사용해보니,훨씬 코드의 의도가 명확해지고 간결하다. 

export default function Toggle() {
  const { count, increment } = useCounter(0);

  return (
    <div>
      <p> useCounter : {count}</p>
      <button type="button" onClick={increment}> 
        useCounter hook 버튼
      </button>
    </div>
  );
}

⚙️ useEffectOnce

  • 의존성 배열을 빈 배열로 넣어서 한 번만 실행하는 Effect를 사용하는 경우가 많은데 useEffectOnce hook 이름에서부터 의도가 명확히 드러난다.

const [products, setProducts] = useState<Product[]>([]);

useEffectOnce(() => {
  const fetchProducts = async () => {
  const url = 'http://localhost:3000/products';
  const response = await fetch(url);
  const data = await response.json();
  setProducts(data.products);
 };

 fetchProducts();
});

return products;

⚙️ useFetch

  • 정말 간단히 쓸 때 좋음, 그러나 기능이 많지 않다.

export default function useFetchProducts() {
  const url = 'http://localhost:3000/products';
  const { data } = useFetch(url);
  if (!data) { 
    return []; 
  }
  return data.products;
}
  • 몇 가지 기능이 살짝 더 있는 useFetch 라이브러리가 따로 있다. → use-http (많이 사용하진 않는다.)

  • 사용법이 더 복잡헤도 괜찮다면, 캐시 이슈를 고려하는 다른 대안의 라이브러리가 있다.

SWR을 사용하면 컴포넌트는 주기적으로 데이터가 바뀌었는지 확인한다. 예를 들어, 게시판이면 게시물이 올라왔는지 확인한다. React Query는 이보다 더 복잡한 것을 다룰 때 사용한다.

⚙️ useInterval

⚙️ useEventListener

  • ⭐️ 강력 추천 ⭐️

  • 모든 종류의 이벤트를 확인할 수 있다.

  • 특히 dispatchEvent로 전달되는 커스텀 이벤트에 반응하기 좋다.

⚙️ useLocalStorage

  • LocalStorage에 객체를 넣는 경우가 많다. 이와 같은 경우 stringfy 와 parse를 자동으로 해준다.

  • 이벤트를 통해(dispatchEvent + useEventListener) 다른 컴포넌트와 동기화하는 게 매우 중요한 특징

⚙️ useDarkMode

  • os 운영체제의 다크테마를 활용하고 싶을 때

✍🏻 Custom Hook, usehooks-ts 정리

  • Custom Hook을 활용한다면 재사용 측면에서 리액트의 강점을 제대로 사용 할 수 있다. 재사용 할 수 있도록 로직을 잘 생각해야 할 것 같다.

  • usehooks-ts 참고 할만 한 내용이 많고, 활용성 측면 야살님은 추천한다.

  • 별도 설치 없이 코드를 복사해서 사용해도 좋고, Custom Hook의 활용 할 수 있는 방법이 많기 때문에 자주 보면서 영감을 얻을 수 있다.

🔗 참고

Last updated