본문 바로가기
[FrontEnd]/React

React - Custom Hook 만들기

by 황원용 2023. 6. 6.
728x90

Custom Hook

  • 여러 컴포넌트에서 반복적으로 사용되는 로직을 Custom Hook으로 만들어 재사용할 수 있다.
  • 이름은 반드시 use로 시작한다.
  • 내부에서 다른 Hook을 호출하는 하나의 자바스크립트 함수이다.

 

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

function UserStatus(props) {
	const [isOnline, setOnline] = useState(null);
    
    useEffect(() => {
    	function handleStatusChange(status) {
        	setIsOnline(status.isOnline);
        }
        
        ServerAPI.subscribeUserStatus(props.user.id, handleStatusChange);
        return () => {
        	ServerAPI.unsubscribeUserStatus(props.user.id, handleStatusChange);
        };
    });
    
    if (isOnlinde === null) {
    	return '대기중...';
    }
    return isOnlinde ? '온라인' : '오프라인';
}
  • 이 코드에 나오는 UserStatus라는 컴포넌트는 isOnline이라는 state에 따라서 사용자의 상태가 온라인인지 아닌지를 텍스트로 보여주는 컴포넌트이다.
  • 동일한 웹사이트에서 연락처 목록을 제공하는데 이때 온라인인 유저는 초록색으로 표시하고 싶다고 가정해 보자.

 

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

function UserListItem(props) {
	const [isOnline, setOnline] = useState(null);
    
    useEffect(() => {
    	function handleStatusChange(status) {
        	setIsOnline(status.isOnline);
        }
        
        ServerAPI.subscribeUserStatus(props.user.id, handleStatusChange);
        return () => {
        	ServerAPI.unsubscribeUserStatus(props.user.id, handleStatusChange);
        };
    });
    
    return (
    	<li style={{ color: isOnlinde ? 'green' : 'black' }}>
        	{props.user.name}
        </li>
    );
}
  • 이를 수행할 컴포넌트의 이름을 UserListItem이라고 지었다.
  • 코드를 보면 앞에 나오는 useStatus와 useState, useEffect 부분이 똑같다는 것을 확인할 수 있다.
  • 이제 이 중복된 부분을 추출하여 Custom Hook을 만들어보자.

 

Custom Hook 추출하기

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

function useUserStatus(props) {
	const [isOnline, setOnline] = useState(null);
    
    useEffect(() => {
    	function handleStatusChange(status) {
        	setIsOnline(status.isOnline);
        }
        
        ServerAPI.subscribeUserStatus(props.user.id, handleStatusChange);
        return () => {
        	ServerAPI.unsubscribeUserStatus(props.user.id, handleStatusChange);
        };
    });
    
    return isOnline;
}
  • 위 두 코드에서 중복된 부분을 추출한 컴포넌트이다.
  • Custom Hook은 별다른 규칙이 없다. 파라미터로 무엇을 받을지, 어떤 것을 리턴해야 할지를 개발자가 정할 수 있다.
  • 이런 점에서 Custom Hook은 단순한 함수와도 같다고 할 수 있다.
  • 단, 이름을 Use로 시작해 이것이 단순한 함수가 아닌 리액트 Hook이라는 것을 나타내준다.

 

Custom Hook 사용하기

function UserStatus(props) {
	const isOnline = useUserStatus(props.user.id);
    
    if (isOnlinde === null) {
    	return '대기중...';
    }
    return isOnlinde ? '온라인' : '오프라인';
}

function UserListItem(props) {
	const isOnline = useUserStatus(props.user.id);
    
    return (
    	<li style={{ color: isOnline ? 'greem' :'black' }}>
        	{props.user.name}
        </li>
    );
}
  • Custom Hook의 이름은 꼭 use로 해야 한다.
  • 여러 개의 컴포넌트에서 하나의 Custom Hook을 사용할 때 컴포넌트 내부에 있는 모든 state와 effects는 분리되어 있다.
    • 리액트 컴포넌트는 각각의 Custom Hook 호출에 대해서 분리된 state를 얻게 되기 때문이다.
    • 각 Custom Hook의 호출 또한 완전히 독립적이다.

 

Hook 간에 데이터를 공유하는 방법

Const userList = [
	{id : 1, name: 'kane'},
    {id : 1, name: 'son'},
    {id : 1, name: 'lukas'},
];

function chatUserSelector(props) {
	const [userId, setUserId] = useState(1);
    const isUserOnline = useUserStatus(userId);
    
    return (
    	<>
        	<Circle color={isUserOnline ? 'green' : 'red'} />
            <select
            	value={userId}
                onchange={event => setUserId(Number(event.target.value))}
            >
            	{userList.map(user => (
                	<option key={user.id} value={user.id}>
                    	{user.id}
                    </option>
                ))}
            </select>
        </>
    );
}
  • 이 컴포넌트는 select 태그를 통해 목록에서 사용자를 선택할 수 있게 하고, 사용자를 선택할 경우 사용자가 온라인인지 아닌지를 보여주게 된다.

 

const [userId, setUserId] = useState(1);
const isUserOnline = useUserStatus(userId);
  • 위 코드에서 이 부분을 보면 useState() Hook을 사용해서 useId라는 state를 만들었다. 현재 선택된 사용자의 아이디를 저장하기 위한 용도이다.
  • 이 userId는 다음에 나오는 useUserStatus()의 파라미터 값으로 들어가게 된다.
  • 이렇게 하면 setUserId() 함수를 통해 userId가 변경될 때마다 useUserStatus() Hook은 이전에 선택된 사용자를 구독 취소하고 새로운 선택된 사용자의 온라인 여부를 구독하게 된다.
  • Hook 간의 데이터 공유는 이러한 방식으로 진행된다.

 

 

 

참고

인프런 - 처음 만난 리액트

728x90

'[FrontEnd] > React' 카테고리의 다른 글

React - Conditional Rendering과 Inline Conditions  (3) 2023.07.01
React - Handling Events  (0) 2023.06.17
React - Hooks  (0) 2023.06.02
React - State & Lifecycle  (0) 2023.06.02
React - Components & Props  (0) 2023.06.02