custom Hooks

2024. 11. 4. 16:29React

Custom Hooks는 React에서 재사용 가능한 상태 로직을 정의하는 방법입니다. 기본 제공되는 훅(useState, useEffect, 등)을 조합하여 고유의 로직을 가진 훅을 만들 수 있으며, 이렇게 만든 훅은 다양한 컴포넌트에서 공통된 기능을 재사용할 수 있게 합니다.

1. Custom Hook의 개념

React에서 Hooks는 컴포넌트의 상태와 생명주기 기능을 관리하는 데 사용됩니다. Custom Hook은 이 기본 훅들을 결합하여 복잡한 로직을 별도로 분리해 둔 함수입니다. Custom Hook은 보통 use로 시작하는 이름을 가지며, 상태 관리 로직을 하나의 독립된 함수로 작성해 필요한 컴포넌트에서 쉽게 가져다 사용할 수 있도록 만들어집니다.

예를 들어, 데이터 가져오기 로직을 여러 컴포넌트에서 사용해야 한다면 useFetch라는 Custom Hook을 만들어 재사용할 수 있습니다.

2. Custom Hook을 만드는 이유

Custom Hook을 사용하면 코드를 더 간결하게 유지하고, 로직을 반복하지 않고 재사용할 수 있습니다. 복잡한 비즈니스 로직이나 공통적으로 사용하는 데이터 로딩, 폼 처리, 인증 등을 Custom Hook으로 분리하면 다음과 같은 장점이 있습니다:

  • 재사용성: 특정 컴포넌트에 국한되지 않고, 다양한 컴포넌트에서 사용 가능한 로직을 하나의 Custom Hook으로 만들어 재사용할 수 있습니다.
  • 가독성 향상: 컴포넌트의 핵심 UI 로직과 상태 로직을 분리하여, 컴포넌트의 코드가 더 깔끔해집니다.
  • 테스트 용이성: Custom Hook을 별도로 테스트하기 쉽기 때문에, 복잡한 로직의 단위 테스트 작성이 용이해집니다.

3. Custom Hook의 기본 구조

Custom Hook은 use로 시작하는 일반 함수입니다. 함수 내부에서 상태(useState), 생명주기 관리(useEffect), 또는 기타 훅들을 사용하여 상태 관리 로직을 정의하고, 최종적으로 데이터나 함수를 반환하여 컴포넌트에서 사용할 수 있게 합니다.

import { useState, useEffect } from 'react';

function useCustomHook() {
  const [state, setState] = useState(initialValue);

  useEffect(() => {
    // 실행할 로직
  }, []);

  return state; // 또는 여러 상태나 함수 반환
}

4. 예제 1: 데이터 가져오기용 Custom Hook - useFetch

useFetch라는 Custom Hook을 만들어, 특정 URL에서 데이터를 가져오는 로직을 재사용할 수 있도록 만들어 보겠습니다.

useFetch Custom Hook

import { useState, useEffect } from 'react';

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

  useEffect(() => {
    const fetchData = async () => {
      setLoading(true);
      setError(null);

      try {
        const response = await fetch(url);
        if (!response.ok) {
          throw new Error(`Error: ${response.status} ${response.statusText}`);
        }
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [url]); // URL이 변경될 때마다 데이터를 다시 가져옴

  return { data, loading, error };
}

export default useFetch;

설명

  • url 파라미터: useFetch 훅은 url 파라미터를 받아, 해당 URL에서 데이터를 가져옵니다.
  • 상태 관리: data, loading, error 세 가지 상태를 관리하여 요청의 상태를 나타냅니다.
  • useEffect: url이 변경될 때마다 useEffect가 실행되어 데이터를 다시 가져옵니다.
  • 반환 값: { data, loading, error } 객체를 반환하여, 훅을 사용하는 컴포넌트에서 필요한 상태를 바로 사용할 수 있게 합니다.

사용 예제

import React from 'react';
import useFetch from './useFetch';

function App() {
  const { data, loading, error } = useFetch('https://api.example.com/data');

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error}</p>;

  return (
    <div>
      <h1>Data:</h1>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
}

export default App;

설명:

App 컴포넌트는 useFetch Custom Hook을 사용하여 간단한 코드로 데이터 가져오기 로직을 처리할 수 있습니다. data, loading, error 상태를 반환하므로, 각 상태에 맞는 UI를 조건부로 렌더링합니다.


5. 예제 2: 입력값 관리 Custom Hook - useInput

입력값을 처리하는 로직이 여러 곳에서 반복될 때, useInput이라는 Custom Hook을 만들어 입력값을 손쉽게 관리할 수 있습니다.

useInput Custom Hook

import { useState } from 'react';

function useInput(initialValue) {
  const [value, setValue] = useState(initialValue);

  const handleChange = (e) => {
    setValue(e.target.value);
  };

  const reset = () => setValue(initialValue);

  return { value, onChange: handleChange, reset };
}

export default useInput;

설명:

  • valuesetValue 상태: useState를 통해 입력값을 관리합니다.
  • handleChange 함수: 입력값이 변경될 때마다 value를 업데이트합니다.
  • reset 함수: 입력값을 초기화하는 함수로, 필요한 경우 원래 값으로 되돌릴 수 있습니다.
  • 반환 값: { value, onChange, reset } 객체를 반환하여, 입력값을 편리하게 관리할 수 있습니다.

사용 예제

import React from 'react';
import useInput from './useInput';

function FormComponent() {
  const name = useInput('');
  const email = useInput('');

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log("Name:", name.value);
    console.log("Email:", email.value);
    name.reset();
    email.reset();
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" placeholder="Name" {...name} />
      <input type="email" placeholder="Email" {...email} />
      <button type="submit">Submit</button>
    </form>
  );
}

export default FormComponent;

설명:

  • {...name}{...email}: useInput에서 반환된 객체를 펼쳐(spread) <input> 태그에 전달하여 입력값 관리 로직을 간결하게 적용합니다.
  • handleSubmit: 폼 제출 시 입력값을 확인하고, reset 함수를 호출하여 입력 필드를 초기화합니다.

이렇게 Custom Hook을 사용하면 폼 처리 로직을 재사용할 수 있으며, 입력값 관련 상태 관리 코드가 간결해집니다.


6. Custom Hook의 주의 사항

  • 의존성 관리: Custom Hook 내부에서 useEffect를 사용할 때 의존성 배열을 적절하게 설정해야 합니다. 의존성 배열이 누락되면 무한 루프가 발생할 수 있습니다.
  • 이름 규칙: Custom Hook은 use로 시작해야 React가 이를 Hook으로 인식하고 훅의 규칙을 적용합니다.
  • 상태와 생명주기 관리의 일관성: Custom Hook은 상태와 생명주기 관리의 일관성을 유지하는 것이 중요합니다. 여러 컴포넌트에서 공통적으로 사용되므로, 예상치 못한 부작용이 없도록 해야 합니다.

Custom Hook을 활용한 개발의 장점

  1. 재사용 가능한 코드: 여러 컴포넌트에서 동일한 로직이 필요할 때, Custom Hook을 통해 코드를 중복하지 않고 재사용할 수 있습니다.
  2. 가독성 향상: 컴포넌트에서 불필요하게 상태 관리나 비즈니스 로직을 분리하여 UI 코드의 가독성을 높일 수 있습니다.
  3. 유지보수 용이성: 특정 로직을 한 곳에 집중하여 관리하기 때문에 유지보수가 쉽고, 로직 수정 시 다른 컴포넌트에 쉽게 적용할 수 있습니다.

정리

Custom Hook은 React에서 공통된 로직을 재사용하고 코드의 유지보수성을 높이는 강력한 도구입니다. 데이터 가져오기, 폼 관리, 이벤트 처리, 인증 등 다양한 영역에서 활용

'React' 카테고리의 다른 글

React  (2) 2024.11.10
POST(생성), useHistory  (0) 2024.11.04
useEffect, fetch()  (0) 2024.11.04
react-router-dom  (0) 2024.11.04
json-server, RESTful API  (0) 2024.11.04