Dev/React.js

[React] Custom Hooks

隣席の開発者群 2023. 6. 28. 16:23
반응형

오랜만에 React 게시물을 가져왔다. 요 근래 이직 준비랍시고 JS 자체에만 너무 많은 관심을 가졌는데, 그래도 React 하면서 알게 된 것들도 정리를 게을리 하면 안되기 때문에 가져왔음.. 

오늘 해볼 얘기는 Custom Hook에 대한 이야기인데 이 Hook 에 대한 개념자체가 조금 까다롭다보니, 한번 복습 때리고 커스텀 훅으로 넘어가볼 거다. 

 

1) Hook

hook을 가장 잘 보여주는 단편적인 예시

난 Hook이라고 하면 "히히 못가" 가 제일 먼저 떠오르는데 그 이유가 뭐냐하면 리액트 컴포넌트를 마운트 시킨다고하면 Hook 이 딸려오는거라고 이미징 했기 때문이다. 당연히 스코프 같은 개념들이 적용되서 만들어지는 효과지만, 컴포넌트 하나를 그리려고 하면 리액트 컴포넌트 내에서 사용한  Hook이 덤으로 딸려오기 때문에 이렇게 이미징을 했다. 

 

Hook은 함수형 컴포넌트를 사용하게 되면서 한번 실행되면 사라지는 함수의 특성을  보완하기 위해 만들어졌다고 나는 이해하고 있다. 솔직히 내가 이해한 방법이 맞는지도 모르겠고 반쪽짜리일 수도 있긴 하지만 일단 설명해보자고 하면 함수 내에서 선언한 변수들은 함수가 실행 되고나면 사라져버리는데, 컴포넌트는 사용자들에게 관련 데이터를 보여주기 위해 해당 변수를 유지해야하는 입장이다. 그래서 함수는 Scope 내에 있던 걸 기억하고 있는다는 특성을 활용했다고 이해했다.  

 

내가 이해한 것들에 대한 관련 배경지식들은 앞선 글들의 링크를 달아두겠다. 

2023.04.20 - [Dev/JavaScript] - [JavaScript] Scope & Closure

 

[JavaScript] Scope & Closure

순서가 조금 잘못된 것 같긴한데, 어쩔 수 없다고 생각한다. 체계적으로 공부를 해서 기초부터 차근차근 닦아올려가며 일을 하게 된 것이 아니라 당장 오늘 이 코드를 작성하지 못하면 큰일난다

openotadev.tistory.com

2023.05.02 - [Dev/React.js] - [React] 함수형 프로그래밍과 hooks

 

[React] 함수형 프로그래밍과 hooks

2023.04.20 - [Dev/JavaScript] - [JavaScript] Scope & Closure 저번 글에서 React의 컴포넌트 생명주기 이야기를 했었는데, 어찌 됐던 초창기 리액트의 클래스형 컴포넌트와 지금 많이 사용하고 있는 함수형 컴포

openotadev.tistory.com

위의 게시물들을 보고 오면 알겠지만, React가 제공하는 Hooks을 사용하는데 있어서는 규칙이라는게 있다. 

최상위 (At the Top Level)에서만 Hook을 호출해야합니다.
반복문, 조건문 혹은 중첩된 함수 내에서 Hook을 호출하지 마세요. 대신 early return이 실행되기 전에 항상 React 함수의 최상위(at the top level)에서 Hook을 호출해야 합니다. 이 규칙을 따르면 컴포넌트가 렌더링 될 때마다 항상 동일한 순서로 Hook이 호출되는 것이 보장됩니다. 이러한 점은 React가  useState 와 useEffect 가 여러 번 호출되는 중에도 Hook의 상태를 올바르게 유지할 수 있도록 해줍니다.


오직 React 함수 안에서만 Hook을 호출해야합니다.

Hook을 일반적인 JavaScript 함수에서 호출하지 마세요. 대신 아래와 같이 호출할 수 있습니다.

  • ✅ React 함수 컴포넌트에서 Hook을 호출하세요.
  • ✅ Custom Hook에서 Hook을 호출하세요.

이 규칙을 지키면 컴포넌트의 모든 상태 관련 로직을 소스코드에서 명확하게 보이도록 할 수 있습니다.

import React from 'react';

const Form = (props) => {
	const [state, setState] = useState('');
    
    
    if (state) {
    	useEffect(() => {
    		
    	}, [])
    }
    
    return (
    	<div>
        	<h1>HI</h1>
        </div>
    )
}

이게 하면 안된다는 거의 첫번째 라고 보면 된다. 위에서 써놓은 형태가 일반적인 자바스크립트의 함수 내에서 훅을 호출했다는 얘기인데, 만약에 저 if 문이 Event 를 통해 실행되는 함수여도 마찬가지이다. hooks는 매번 렌더링 될때마다 동일하게 호출이 이뤄져야한다. 그래야 각 hooks 끼리 의존하고 실행되는 결과가 동일하게 흘러간다고 보장되기 때문이다. 

 

 

2. Custom Hook 사용방법

 

근데 우리는 오늘 이걸 살펴볼게 아니라, 두번째 이야기를 할거다. 

위의 Form의 경우 React 함수다. React 함수가 뭐냐, jsx파일에서 쓰는 거 얘기하는거다.  return (<div></div>) 이게 있는 함수 얘기임.

근데 사람이 쓰다보면 재사용도 하고 싶고, 좀 처음에 가지고 있는 State값을 바로 쓰기보단 전처리도 좀 해주고 싶고, 코드 라인 수도 줄이고 싶기 나름이다. 그래서 위에서 말한 것들을 하려고, 자바스크립트 함수 안에서 Hooks를 호출하게 해둔 다음, 그거 export 하고 import 해서 쓰고 싶은거임. 근데 그거하면 안된다는 뜻이다. 그걸 위해서 Custom Hook이란걸 할 수 있게 해놨으니, 쓰고 싶으면 use붙여서 훅으로 만든 뒤에 쓰렴? 이 말과도 같다. 

 

예시로 한번 일단 Custom Hook 코드를 작성해보자

const useFoo = () => {
	const [stateOne, setStateOne] = useState(0);
    const [stateTwo, setStateTwo] = useState(0);
    const [stateThree, setStateThree] = useState(0);
    const [stateFour, setStateFour] = useState(0);
    const [stateFive, setStateFive] = useState(0);
    const [stateSix, setStateSix] = useState(0);
    const [stateSeven, setStateSeven] = useState(0);
    
    return {
    	stateOne,
        setStateOne,
        stateTwo,
        setStateTwo,
        ...
    }
}

그니까 대충 이런 식으로 쓰면 Custom Hook을 "선언"했다고 할 수 있다. 그리고 호출 자체를 하기 위해서는

import React from 'react';

const Form = ({props}) => {
	const [state, setState] = useState('');
    const {stateOne, setStateOne} = useFoo();
    
    
    if (state) {
    	useEffect(() => {
    		
    	}, [])
    }
    
    return (
    	<div>
        	<h1>HI</h1>
        </div>
    )
}

이런 느낌으로 갖다가 쓰는거임.

결론적으로 Custom Hook은 별도로 상태들이랑, 그 상태들을 지지고 볶을 로직을 미리 구현해두고 컴포넌트에서 그 지지고 볶아진 상태들을 사용하고자 만들었다는 것이다. 

처음에 Custom Hook이라는게 마냥 어렵게만 들려서 나도 겁먹었었는데, 오히려 그냥 Hook의 존재이유 자체를 이해하는게 더 힘들었다. 왜냐면 이거 이해하려면 자바스크립트 함수에 대해서도 공부해야하고 따라서 Scope도 이해해야하는데, 그런 힌트를 주는 사람은 아무도 없으니까.

LIST