React 8. Hook 2

@t189216·2024년 3월 7일

😎 프론트엔드

목록 보기
20/31

Hook의 규칙


↗️ (이전 포스트) Hook이란?

  1. Hook은 무조건 최상위 레벨에서만 호출해야 합니다. 여기서 말하는 최상위 레벨은 React 함수 컴포넌트의 최상위 레벨을 의미합니다. 따라서 반복문이나 조건문 또는 중첩된 함수들 안에서 Hook을 호출하면 안됩니다.

  2. Hook은 컴포넌트가 렌더링될 때마다 매번 같은 순서로 호출되어야 합니다.

  3. React 함수 컴포넌트에서만 Hook을 호출해야 합니다. React 컴포넌트에 있는 state와 관련된 모든 로직은 소스 코드를 통해 명확히 확인이 가능해야 합니다.

eslint-plugin-react-hooks

Hook의 규칙을 따르도록 강제해주는 플러그인입니다. eslint는 자바스크립트 코드에서 발견되는 문제 패턴을 식별하기 위한 정적 코드 분석 도구입니다.

🌐 공식 홈페이지

Custom Hook 만들기

여러 컴포넌트에서 반복적으로 사용되는 로직을 Hook으로 만들어 재사용하기 위해 커스텀 훅을 만들수도 있습니다. 이름이 use로 시작하고 내부에서 다른 Hook을 호출하는 하나의 자바스크립트 함수라고 보면 됩니다.

Custom Hook 예시 #1

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

function UserStatus(props) {
    const [isOnline, setIsOnline] = useState(null);

    useEffect(() => {
        function handleStatusChange(status) {
            setIsOnline(status.isOnline);
        }
    
        ServerAPI.subscribeUserStatus(props.user.id, handleStatusChange);
        return () => {
            ServerAPI.unsubscribeUserStatus(props.user.id, handleStatusChange);
        };
    });

    if (isOnline === null) {
        return "대기 중...";
    }
    return isOnline ? '온라인' : '오프라인';
}

UserStatus 컴포넌트는 isOnline이라는 state에 따라서 사용자의 상태가 온라인인지 아닌지를 텍스트로 보여주는 컴포넌트입니다.

동일한 웹사이트에서 연락처 목록을 제공하는데 이 때, 온라인인 사용자의 이름은 초록색으로 표시하고 싶습니다. 이 컴포넌트의 이름을 UserListItem이라고 해봅시다.

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

function UserListItem(props) {
    const [isOnline, setIsOnline] = 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: isOnline ? 'green' : 'black'}}>
            {props.user.name}
        </li>
    );
}

앞에 나온 UserStatus와 UseState, UseEffect훅을 사용하는 부분이 중복됩니다. 중복되는 로직을 Custom Hook으로 추출해봅시다.

import { useState, useEffect } from 'react';

function useUserStatus(userId) {
    const [isOnline, setIsOnline] = useState(null);

    useEffect(() => {
        function handleStatusChange(status) {
            setIsOnline(status.isOnline);
        }
    
        ServerAPI.subscribeUserStatus(props.user.id, handleStatusChange);
        return () => {
            ServerAPI.unsubscribeUserStatus(props.user.id, handleStatusChange);
        };
    });

    return isOnline;
}

다른 Hook으로 추출하는 것은 무조건 커스텀 Hook의 최상위 레벨에서만 가능합니다.

커스텀 Hook은 규칙이 없습니다. 파라미터로 무엇을 받을지, 어떤 것을 리턴해야 할지 개발자가 직접 정할 수 있습니다.

Custom Hook 적용하기

function UserStatus(props) {
    const isOnline = useUserStatus(props.user.id);

    if (isOnline === null) {
        return '대기중...';
    }
    return isOnline ? '온라인' : '오프라인';
}

function UserListItem(props) {
    const isOnline = useUserStatus(props.user.id);

    return (
        <li style={{ color: isOnline ? 'green' : 'black'}}>
            {props.user.name}
        </li>
    );
}

커스텀 Hook 은 리액트 기능이 아닌 Hook의 디자인에서 자연스럽게 따르는 규칙입니다.

단순히 state와 관련된 로직을 재사용 가능하게 만든 것이므로 여러 개의 컴포넌트에서 하나의 커스텀 Hook 을 사용할 때에 컴포넌트 내부에 있는 모든 state와 effect는 전부 분리되어 있습니다.

커스텀 Hook 의 호출 또한 완전히 독립적이다.

profile
Today I Learned

0개의 댓글