Amada Coding Club

[React Hook] 리액트 Hook 총정리(4) - Hook 사용 규칙, Hook 제작방법 본문

Front-End/React

[React Hook] 리액트 Hook 총정리(4) - Hook 사용 규칙, Hook 제작방법

아마다회장 2023. 1. 28. 16:14

 

 

[React Hook] 리액트 Hook 총정리(3) - useEffect

2023.01.20 - [Front-End/React] - [React Hook] 리액트 Hook 총정리(2) - useState [React Hook] 리액트 Hook 총정리(2) - useState 2023.01.17 - [Front-End/React] - [React Hook] 리액트 Hook 총정리(1) - Hook이란? [React Hook] 리액트 Hook 총

amadaclub.tistory.com

설 명절이랑 여러 권태를 보내고 다시 시작한다. 

지난 시간에 살펴본 useState와 useEffect, 그리고 여러 Hook을 사용하기 위해선 두 가지 규칙을 지켜야한다.

그 규칙에 대해 한 번 알아보고 custom hook을 제작하는 방법에 대해 살펴보자


Hook 규칙

Hook을 사용하기 위해 지켜야되는 규칙은 두 가지가 있다. 

 

1. 최상위에서 Hook을 호출해야 한다.

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

 

하나하나 천천히 살펴보자

1. React 함수 최상위에서 Hook을 호출해야 한다. 

import React from 'react'
function Conponent(){
	// 최상단
    
	// ~~여러 로직
	return (
    <div>
    	//~~~여러 리턴 JSX태그들
    </div>
    )
}

export default Conponent;

위와 같은 컴포넌트가 있을 때 Hook을 호출하는 부분은 리액트 함수의 최상단에 위치해야한다. 

이는 컴포넌트가 렌더링 될 때마다 hook이 호출되는 순서가 항상 동일하게 유지되는 것을 보장한다. 또한, Hook의 상태를 올바르게 유지하는데에도 도움을 준다. 조건문이나 반복문 안에 hook을 호출하면 안된다! 

왜 조건문이나 반복문안에 hook을 호출하면 안되는지 예시를 보자

function Form() {
  const [name, setName] = useState('Mary');

  useEffect(function persistForm() {
    localStorage.setItem('formData', name);
  });

  const [surname, setSurname] = useState('Poppins');

  useEffect(function updateTitle() {
    document.title = name + ' ' + surname;
  });

  // ...
}

이전 게시글에서 봤다시피 hook은 여러번 사용해도 상관없다. 

위 컴포넌트는 name을 저장하고 effect를 통해 local storage에 name값을 저장하고 다시 surname을 저장하고 페이지의 title을 수정한다. 

이때 다시 렌더링이 되면 리액트는 이전 hook 호출 순서를 기반으로 어떤 state가 어떤 useState호출에 해당하는지 알 수 있다. 

만약에

if(name !== ""){
	useEffect(function persistForm() {
        localStorage.setItem('formData', name);
      });
}

이렇게 조건문 안에 hook을 호출한다면

만약에 조건이 false가 되어 해당 hook을 호출하지 못하게 된다면

이전의 hook 호출 순서와 달라져 이전 호출 순서에 의존하는 React의 특성상 이후 호출되는 hook의 순서가 달라져 리렌더링 시 버그가 일어난다. 그래서 hook은 컴포넌트 함수의 최상단(즉, 조건문이나 반복문 안에 위치하지 않고 특정 상황이 아닌 항상 실행되는 위치)에 있어야 하고 만약 조건문을 넣고 싶다면 아래와 같이 hook안에서 실행해야 한다.

  useEffect(function persistForm() {
    if (name !== '') {
      localStorage.setItem('formData', name);
    }
  });

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

이건 뭐 당연한 건데 일반 자바스크립트 함수에서는 hook을 호출하면 안되고 React 컴포넌트 안에서 Hook을 호출하고 Custom Hook에서 hook을 호출해야 한다. 이는 상태 관련 로직들을 소스코드에서 명확하게 보이게 할 수 있다. 

 

자 이제 규칙에 대해 알아보았으니 Custom hook을 제작하는 방법에 대해 알아보자.


Custom Hook 제작

Custom Hook을 제작을 어렵다고 생각한다. 물론 나도 Custom Hook을 어렵다고 생각했다. 그런데 생각보다 막 어렵지는 않다!

먼저 custom hook을 만들기 위한 규칙은 그렇게 많지 않다. 자신이 받고 싶은 인자나 반환값을 마음대로 설정할 수 있다. 하나 지켜야하는 점은 hook을 제작할 때는 이름에 use를 붙여야 한다. 

Hook을 왜 제작할까?

제일 큰 이유는 어떤 로직이 중복되어 사용될 때 같은 코드를 반복해서 입력하는 걸 막기 위해 사용한다. 만약 유저의 접속여부를 확인하는 로직을 A와 B에서 같이 사용할 때 Hook을 이용해서 사용한다면 코드의 길이를 줄일 수 있을 뿐만 아니라 유지보수에도 큰 도움을 줄 수 있다.

hook 제작 예시는 https://ko.reactjs.org/docs/hooks-custom.html

 

자신만의 Hook 만들기 – React

A JavaScript library for building user interfaces

ko.reactjs.org

여기를 참조하길 바란다.

같은 hook을 다른 곳에서 여러 번 사용하더라도 각 hook은 독립적으로 작용해서 영향을 미치지 않는다.

또한 hook에서 나온 값을 다른 hook에 값을 전달할 수 있다.

즉, 로직 공유의 유연성을 제공한다. 그러나 무작정 hook을 만들어내려 하지 않고 복잡한 로직을 단순한 인터페이스 속에 숨기게 할 수 있는지, 너무 복잡하게 엉켜있어 풀어야하는 경우인지 확인하고 제작하는 것을 추천한다. 

 

이제 또 다른 hook들에 대해 알아보자

2023.01.28 - [Front-End/React] - [React Hook] 리액트 Hook 총정리(5) - useMemo useCallback (React.memo)

 

[React Hook] 리액트 Hook 총정리(5) - useMemo useCallback (React.memo)

2023.01.28 - [Front-End/React] - [React Hook] 리액트 Hook 총정리(4) - Hook 사용 규칙, Hook 제작방법 [React Hook] 리액트 Hook 총정리(4) - Hook 사용 규칙, Hook 제작방법 [React Hook] 리액트 Hook 총정리(3) - useEffect 2023.01.

amadaclub.tistory.com

 

참조

https://ko.reactjs.org/docs/hooks-custom.html

https://ko.reactjs.org/docs/hooks-rules.html#explanation