React

[Hook] Custom Hook

Mia_ 2023. 1. 23. 21:08

Custom Hooks

: 개발자가 스스로 커스텀한 Hook. 이를 이용해 반복되는 로직을 함수로 뽑아내어 재사용 할 수 있음!

 

자주 사용되는 케이스

- 여러 URL을 fetch할 때 

- 여러 input에 의한 상태 변경 

- 위 처럼 반복되는 로직을 동일한 함수에서 작동하게 하고 싶을 때 주로 사용

 

이용 시 장점 

- 상태 관리 로직의 재사용 가능 

- 클래스 컴포넌트보다 적은 양의 코드로 동일한 로직이 구현 가능

- 함수형으로 작성하기 때문에 보다 명료함 

 

Custom Hook 사용 규칙

- Custom Hook을 정의할 때 함수 이름 앞에 use를 붙이는 것

- 대개의 경우 프로젝트 내의 hooks 디렉토리에 Custom Hook을 위치 시킴

- Custom Hook을 만들 때 함수는 조건부 함수가 아니여야 함 → 즉, return 하는 값은 조건부여서는 안됨!

- Custom Hook은 useState와 같이 리액트 내장 Hook을 사용하여 작성 할 수 있음 (일반 함수 내부에서 리액트 내장 Hook을 불러 사용할 수 없음)

- 같은 Custom Hook을 사용했다고 해서 두 개의 컴포넌트가 같은 state를 공유하는 것은 아님!

 

1. Custom Hook을 사용하지 않은 예시

//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>
  );
}

 

2. 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;
}

 

3. 2 에서 만든 Custom Hook을 이용해 1 을 재작성

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>
  );
}