- 자신만의 Hook를 만들면 컴포넌트 로직을 함수로 뽑아 재사용 할 수 있다.
// 채팅 애플리케이션에서 친구가 온라인인지 아닌지에 대한
// 메시지를 표시하는 컴포넌트
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);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
- 리액트에서는 상태 관련 로직을 컴포넌트에서 공유하는 두 가지의 전통적인 방법이 있다.
- render props
- 고차 컴포넌트
- Hook를 사용하여 트리에 컴포넌트를 더하지 않고 위 문제를 해결 할 수 있다.
사용자 정의 Hook 추출하기
- 두 개의 자바스크립트 함수에서 같은 로직을 공유하고자 할 때는 또 다른 함수로 분리한다. ( 컴포넌트 Hook 또한 함수이다 ! )
- Hook 규칙이 잘 적용되어 있는 Hook임을 명확히 하기 위해 사용자 정의 hook의 이름을 use로 시작하자
// 사용자 정의 Hook, 컴포넌트의 로직과 같다.
import { useState, useEffect } from 'react';
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;
}
- 컴포넌트 처럼 Hook들은 사용자 Hook의 위로 놓여야 하며 사용자 정의 Hook는 조건부 함수가 아니어야 한다.
- 컴포넌트와는 다르게 사용자 정의 Hook는 무엇을 인수로 받아야 하며 무엇을 반환하는지 사용자가 결정 할 수 있다.
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);
// ...
return isOnline;
}
- useFriendStatus Hook의 목표는 친구의 상태를 구독하기 위함이며 이를 위해 friendID를 이수로 받고 온라인 상태 여부를 반환한다.
사용자 정의 Hook 이용하기
- FriendStatus 와 FriendListItem 이라는 두 컴포넌트의 중복되어 있는 로직을 제거 하는 것이 최종 목표다. (두 컴포넌트 모두 친구의 온라인 상태 여부를 알아야 한다)
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>
);
}
- 위에서 두 컴포넌트에서 useFriendStatus Hook를 사용하고 있다.
커스텀 Hook의 이름이 use로 시작하는 이유
- 이 관습을 따르지 않으면 특정한 함수가 그 안에서 Hook를 호출하는지를 알 수 없기 때문에 Hook규칙의 위반 여부를 자동으로 체크할 수 없다.
같은 Hook를 사용하는 두개의 컴포넌트의 state 공유 여부
- 커스텀 Hook는 상태 관련 로직(구독을 설정하고 변수값을 기억하는 정도)를 재사용한다.
- 그 안의 state와 effect는 완전히 독립적이다.
사용자 정의 Hook는 어떻게 독립된 state를 얻는가
- useFriendStatus를 직접적으로 호출하기 때문에 react의 관점에서는 useState와 useEffect를 호출한것과 같다.
- Hook는 하나의 컴포넌트 안에서 useState와 useEffect를 여러번 호출할 수 있고 이들은 모두 독립적이다.
댓글