[React] Custom Hook

LMH·2023년 1월 25일
0
post-thumbnail

이번 포스팅에서는 Custom Hook에 대해서 정리하겠습니다.

Custom Hook이란?

리액트에서 함수형 컴포넌트를 이용해서 개발을 진행하면 useState, useEffect와 같은 내장된 hook을 사용해서 편리하게 원하는 로직을 작성할 수 있습니다.

Custom Hook은 개발자가 스스로 원하는 Hook을 만들어 사용하는 것으로 코드를 재활용하여 코드량을 줄일 수 있습니다. 예를들어 데이터 패칭과 같은 반복된 작업이나 input에 의한 상태 변경 등을 Custom Hook을 통해 쉽게 사용할 수 있습니다.

Custom Hook 규칙

Custom Hook을 사용하기 위해서 몇 가지 규칙이 있는데, 다음과 같습니다.

  1. Custom Hook을 정의할 때는 함수 이름 앞에 use를 붙이는 것이 규칙입니다.
  2. 대개의 경우 프로젝트 내의 hooks 디렉토리에 Custom Hook을 위치 시킵니다.
  3. Custom Hook으로 만들 때 함수는 조건부 함수가 아니어야 합니다. 즉 return 하는 값은 조건부여서는 안 됩니다.

아래의 코드들은 리액트 공식 문서에 있는 컴포넌트입니다. FriendStatus와 FriendListItem 컴포넌트는 useState와 useEffect를 사용한 동일한 로직으로 구현됩니다.

//FriendStatus : 친구가 online인지 offline인지 return하는 컴포넌트
function FriendStatus(props) {
  const [isOnline, setIsOnline] = useState(null);
  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}

//FriendListItem : 친구가 online일 때 초록색으로 표시하는 컴포넌트
function FriendListItem(props) {
  const [isOnline, setIsOnline] = useState(null);
  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

  return (
    <li style={{ color: isOnline ? 'green' : 'black' }}>
      {props.friend.name}
    </li>
  );
}

이런 상황에서 Custom Hook을 만들어 사용할 수 있습니다. useFriendStatus라는 Hook을 만들어 두 컴포넌트에 적용 시킵니다.

// 동일한 로직을 Custom Hook으로 구현
function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null);

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
    };
  });

  return isOnline;
}

FriendStatus, FriendListItem 두 컴포넌트에 동일한 Custom Hook을 사용하더라도 state값은 컴포넌트 내에서 독립적으로 정의됩니다.

// 두 컴포넌트에 useFriendStatus Hook 적용
function FriendStatus(props) {
  const isOnline = useFriendStatus(props.friend.id);

  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}

function FriendListItem(props) {
  const isOnline = useFriendStatus(props.friend.id);

  return (
    <li style={{ color: isOnline ? 'green' : 'black' }}>
      {props.friend.name}
    </li>
  );
}

Reference

https://ko.reactjs.org/

profile
새로운 것을 기록하고 복습하는 공간입니다.

0개의 댓글