본문 바로가기
카테고리 없음

Custom Hooks

by 살길바라냐 2023. 1. 31.

참조: 공식 홈페이지

hook의 규칙

 

사용하는 이유?

 

반복되는 로직을 하나로 묶어서 재사용하기 위함이다. 

개발을 하다 보면 가끔 상태 관련 로직을 컴포넌트 간에 재사용하고 싶은 경우가 생깁니다.
이 문제를 해결하기 위한 전통적인 방법이 두 가지 있었는데,
higher-order components와 render props가 바로 그것입니다.
Custom Hook은 이들 둘과는 달리 컴포넌트 트리에
새 컴포넌트를 추가하지 않고도 이것을 가능하게 해줍니다.
- 리액트 공식 문서-

 

컴포넌트와 가장 큰 차이점은 독립적으로 State 를 생성한다
(머 사실 컴포넌트도 강제로 만들수 있기 하지만)

 

리액트 공식 문서에서 설명한 예제를 가지고 
좀더 쉽게 이해를 해보자

 

import React, { useState, useEffect } from 'react';

function FriendStatus(props) {
  const [isOnline, setIsOnline] = useState(null);
  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }
    // 렌더시에 동작할 함수 
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    
    // componentWillUnmount시에 구현할 함수
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

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

 

import React, { useState, useEffect } from 'react';

function FriendListItem(props) {
  /*
  FriendStatus함수와 비슷함
  */
  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 (
    <View style={{ color: isOnline ? 'green' : 'black' }}>
      {props.friend.name}
    </View>
  );
}

 

FriendStatus FriendListItem 컴포넌트가 각각 있다. 

그런데 작성하다보니 FriendListItem 컴포넌트 내부 코드가
FriendStatus와 비슷하다는 것을 알게 됬다.

그래서 뭔가 효율적인 코드로 리펙토링 하고 싶은데
render props 고차 컴포넌트 다른 방법을 사용 하고 싶다

새로운 customeHook으로 useFriendStatus 만들어 보자

 

import { useState, useEffect } from 'react';

// 함수명 접두사에 use 붙여준다.
// props가 아닌 필요한 인수로 바꿔준다. 
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;
}

 

이제 만든 customeHook을 적용 해보자

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

 

추가적으로 Hook에서 Hook으로 정보를 전달 가능하다
아래와 같이 :)

  const [recipientID, setRecipientID] = useState(1);
  const isRecipientOnline = useFriendStatus(recipientID);

 

요약

  • 특징

1. 기본적으로 hook의 디자인을 따르는 관습이다.

2. 접두어로 반드시 use로 시작되어야 한다. (규칙을 자동 검사하기 위해)

3. custom hook안에 state와 effect는 독립적으로 사용된다.

4. hook과 hook 사이로 정보 전달이 가능하다. 

5. 상태관리 로직의 재활용이 가능하다. (독립적)

 

  • hook의 규칙

1. 최상위 에서만 Hook을 호출해야 한다.
(반복문, 조건문, 중첩된 함수에 절때 사용하면 안된다.
그래 hook이 동일한 순서로 호출하여 사용할 수 있다.)

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

3. 고유성을 보장해야 한다.
(같은 hook 호출하더라고 서로 상태값이 변경이나, 충돌이 나면 안된다.)

 

 

728x90
반응형