[React] 나만의 Custom Hook 만들기

MinJae·2024년 10월 18일
1

React

목록 보기
9/21

리액트는 useState, useEffect, 그리고 useRef 같이 몇몇 내재하고 있는 Hook이 존재합니다. 기본적으로 제공되는 Hook들 이외에 추가적으로 필요한 기능이 있다면 직접 훅을 만들어서 사용할 수 있습니다. 이것을 커스텀 훅(Custom Hook)이라고 부릅니다. 커스텀 훅을 만드는 이유는 여러 컴포넌트에서 반복적으로 사용되는 로직을 훅으로 만들어 재사용하기 위함입니다.

커스텀 훅을 활용한 갤러리 만들기

이 예시에서는 API 호출을 통해 개와 고양이 이미지를 가져오는 커스텀 훅을 만들어서, 이를 활용한 이미지 갤러리 웹 페이지를 구현해 보겠습니다.

result

커스텀 훅 useFetch 만들기

커스텀 훅의 이름은 use로 시작하여 훅이라는 것을 알게 하고 use 뒤에는 대문자로 시작합니다.

리액트의 useStateuseEffect를 이용하여 데이터를 가져오는 비동기 로직을 처리하는 커스텀 훅 useFetch를 작성할 수 있습니다. 이 훅은 데이터를 요청하는 로직을 추상화해 재사용할 수 있도록 만들고, API에서 데이터를 가져오는 동안 상태를 관리합니다.

// useFetch.jsx
import { useEffect, useState } from 'react';

const useFetch = (url) => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const fetchData = () => {
    setLoading(true);
    fetch(url)
      .then((res) => res.json())
      .then((data) => {
        setData(data);
        setLoading(false);
      })
      .catch((err) => {
        setError(err);
        setLoading(false);
      });
  };

  useEffect(() => {
    fetchData();
  }, [url]);

  return { data, loading, error, fetchData };
};
export default useFetch;

코드 설명

1. 상태값 초기화:

  • data: 데이터를 저장하는 상태입니다. 초기값은 null로 설정하고, fetch를 통해 데이터를 받아오면 업데이트됩니다.
  • loading: 데이터를 가져오는 동안 로딩 상태를 관리합니다.
  • error: 에러가 발생했을 때 에러 메시지를 지정합니다.

2. fetchData 함수:

  • fetchData 함수는 주어진 url에서 데이터를 받아오는 비동기 로직을 수행합니다. 데이터를 가져오는 동안 loading 상태를 true로 설정한 후, 성공적으로 데이터를 받아오면 data 상태를 업데이트하고, 실패하면 error 상태를 설정합니다. 데이터를 받아오거나 에러 상태를 업데이트하면 로딩 상태를 false로 돌려놓습니다.

3. useEffect 훅:

  • useEffect는 컴포넌트가 처음 렌더링될 때 fetchData를 호출해 데이터를 받아오도록 설정합니다. 또한, url이 변경될 때마다 데이터를 다시 요청하도록 의존성 배열에 url을 넣었습니다.

4. return:

  • data, loading, error 그리고 fetchData 함수를 리턴하여 컴포넌트에서 사용할 수 있습니다.

커스텀 훅 useFetch 사용하기

작성한 커스텀 훅 useFetch를 활용하여 개와 고양이 이미지를 가져오는 갤러리를 만들어보겠습니다. 버튼 클릭 시마다 새로운 이미지를 요청하고, 로딩 상태나 에러 상태를 관리할 수 있습니다.

// App.jsx
import './App.css';
import useFetch from './useFetch';

const dogUrl = 'https://dog.ceo/api/breeds/image/random';
const catUrl = 'https://api.thecatapi.com/v1/images/search';

function App() {
  const {
    data: dogData,
    loading: dogLoading,
    fetchData: dogFetchData,
  } = useFetch(dogUrl);

  const {
    data: catData,
    loading: catLoading,
    fetchData: catFetchData,
  } = useFetch(catUrl);
  
  return (
    <>
      <h1> Animal gallery</h1>
      <p>
        애니멀 갤러리에 오신 여러분 환영합니다. <br /> 각 버튼을 클릭하여 사진을
        업데이트 해보세요.
      </p>
      <div className="container">
        <h2> 🐶 Dog Zone</h2>
        <button onClick={() => dogFetchData(dogUrl)}>new Dog</button>
        {dogLoading ? (
          <p className="loading">Loading . . .</p>
        ) : (
          dogData && <img src={dogData.message} alt="dog" />
        )}
      </div>
      <div className="container">
        <h2>🐱Cat Zone</h2>
        <button onClick={() => catFetchData(catUrl)}>new Cat</button>
        {catLoading ? (
          <p className="loading">Loading . . .</p>
        ) : (
          catData && <img src={catData[0].url} alt="cat" />
        )}
      </div>
    </>
  );
}

export default App;

코드 설명

1. useFetch 사용:

  • 각각 개와 고양이 이미지를 불러오기 위해 dogUrl과 catUrl에서 데이터를 가져옵니다.
  • 각 fetch 요청에 대한 data, loading 상태를 별도로 관리하며, 버튼 클릭 시 새로운 이미지를 요청할 수 있도록 fetchData 함수를 실행합니다.

2. 조건부 렌더링:

  • 데이터를 가져오는 동안 로딩 중임을 표시하고, 데이터가 정상적으로 로드되면 이미지를 렌더링합니다.
  • 에러가 발생하면 해당 메시지를 표시하고록 할 수 있습니다.

결론

커스텀 훅을 사용하면 이렇게 API 데이터를 여러 컴포넌트에서 손쉽게 불러오고, 공통 로직을 추상화하여 재사용성을 높일 수 있습니다. 이번 예시에서는 단순한 이미지 갤러리였지만, 다양한 비동기 로직을 처리할 때 매우 유용하게 활용할 수 있습니다.


✅ 참고

profile
반갑습니다
post-custom-banner

0개의 댓글