[React] Hooks Custom하기

mj·2021년 7월 26일
0

What is Hooks?

React간 재사용 가능한 로직을 붙이는 방법을 제공하지 않기 때문에 Hook을 통해 계층간의 변화없이 상태 관련 로직을 만들어 재사용할 수 있게 도와줍니다.

React에서는 class component를 사용하기 위해 this를 다룰 줄 알아야 합니다. 자바스크립트의 this는 다른 언어들과 다르게 작동함으로 코드의 재사용과 구성을 어렵게 했기 때문에 Hook을 통해 Class없이 React의 기능을 사용하는 방법을 제시합니다.

다음과 같은 코드가 있습니다.

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

//친구의 상태를 보는 함수
function FriendStatus(props) {
  //useState Hook을 통해 isOnline이라는 state를 관리한다.
  const [isOnline, setIsOnline] = useState(null);
  //useEffect라는 Hook을 통해 handleStatusChange라는 부수효과를 component가
  //rendering 될 때마다 불러오지않고 사용할 때만 호출한다.
  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }
    //구독된 친구의 상태를 ChatAPI로 관리한다.
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });
	
  //아직 isOnline이 null이면 Loading을 반환한다.
  if (isOnline === null) {
    return 'Loading...';
  }
  //isOnline이 true면 'Online'을 false면 'Offline'을 반환한다.
  return isOnline ? 'Online' : 'Offline';
}

이제 이것을 Hook으로 바꿔보겠습니다.

import { useState, useEffect } from 'react';

//hook의 naming은 prefix로 use를 붙인다.
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;
}

Hooks는 조건부 함수가 아니여야 한다. 그리고 최상위(At the top level)에서만 Hook을 호출해야 합니다.
왜냐하면 Hook이 동일한 순서로 호출되어야 합니다. React는 이전 상태와 비교하여 변화된 점만 DOM에 반영하기 때문에 조건문을 사용하여 Hook을 건너뛰게 되면 이전 상태를 알 수 없게 되어 Hook의 상태가 하나씩 밀려 버그를 발생시키게 되기 때문입니다. 그렇기 때문에 최상위에서만 hook을 호출해야 하는 것입니다.

마지막으로 한 번 더 훅을 직접 만들어 보겠습니다.

function useUser(userId) { // 1
  const [user, setUser] = useState(null);
  useEffect(() => {
    getUserApi(uesrId).then(data => setuser(data));
  }, [userId]);
  return user;
}

function Profile({ userId }) { // 2
  const user = useUser(userId);
}

1은 useState와 usEffect hook을 이용해서 커스텀 훅을 만들었다. 이렇게 레고 블록처럼 기존 훅을 이용해서 새로운 훅을 만들 수 있다.

2는 useUser라는 custom hook을 만들어 내부 구현을 숨기면서 사용 편의성을 높일 수 있다.

결론

Hook을 custom할 때에는 규칙을 지켜서 각 훅의 상태를 제대로 기억할 수 있게 해야 한다.
Hook을 사용할 때 조건을 사용하게 되면 호출이 되거나 안될 수도 있으므로 반드시 주의하여야 한다.
왜냐면 useState라는 훅이 어떤 변수를 가르키는지 알 수 없기 때문이다.

0개의 댓글