함수형 컴포넌트에서 state와 생명주기 기능을 "연동"할 수 있게 해주는 함수.
함수형 컴포넌트는 React가 생겨날때부터 클래스형과 함께 존재했다.
함수는 input
이 있고 함수를 거쳐 output
이 나온다. React의 함수형 컴포넌트도 마찬가지다.
//기존 함수
function(input) {return output;}
//React에서
React Component(props) {return jsx;}
React Component
는 props
를 받아 jsx
를 반환한다.
안에서 state
를 선언해준다 하더라도 output
을 반환하고 함수가 끝나면 사라지기 때문에 state
유지가 불가능하다.
그러나 hook
이 등장함으로써 함수형에서도 state
와 lifecycle
기능을 사용 가능하게 되었다.
hook
은 함수형 컴포넌트 안에서 사용하는 함수로 클래스형에서는 사용이 불가하다.hook
자체가 class
없이도 React를 사용할 수 있게 해주기 때문에 상관이 없다.)hook
을 제공함: useState
, useEffect
custom hook
을 만들어 사용 가능.그렇다면 굳이 이미 쓰고있는 클래스형을 버리고 hook
을 만들어 쓰면서까지 함수형으로 갈아타는 이유가 무엇인지를 이야기해보자.
state
와 관련된 로직을 재사용하기 힘들다. HOC
, render props
같은 기능을 쓰다보면 코드가 복잡해짐을 느낀다.lifecycle
정리가 힘들다. 사이클별로 나눠는 써야하는데 그러고나면 막상 관심사별로 분리가 힘들어서 어디에 쓰이는 놈인지 알아보기 힘들다. 함수형에선 useEffect
가 있어 훨 편리하다.this
라던지 state
변화라던지.. 등등 흐름을 따라가기 힘들어진다. 반면에 함수형은 input/output
만 생각하면 된다.this
가 최신 state
를 따라가기 때문에 사용 함수를 중간에 바꿨을 때, 적용시킨 함수에서 마무리를 짓는게 아니라 바뀐 함수에 this
가 적용되어 버린다.아무튼 클래스형은 이것저것 따져 써야하고 뭔가 복잡해서 쓰기 좀 불편하다.
반복문, 조건문, 중첩된 함수 내에서는 hook
호출이 불가하다.
이유는 React가 여러 훅들을 구분하는 유일한 방법이 '사용된 순서'이기 때문이다.
위의 상황에서라면 hook
사용 순서가 매 상황마다 바뀌니 구분이 불가능해진다.
유일한 예외가 custom hook 안에서 호출하는 경우이다.
import React, {useState} from 'react';
const [state, setState] = useState(초기값);
//배열 구조 분해
import React, {useEffect} from 'react';
useEffect(() => {실행 함수}, [의존성 배열])
useEffect(() => {실행 함수; return();}, [의존성 배열])
기존 클래스형에서의 lifecycle
기능을 모조리 대신한다.
의존성 배열
에 아무런 값이 존재하지 않는다면 컴포넌트가 처음 렌더링될 때만 실행한다.의존성 배열
안에 값이 존재한다면 해당 변수에 변동이 생겼을 때마다도 실행된다.클린업 함수(return)
가 작성되었다면 다음 useEffect
가 실행되기 직전, 혹은 컴포넌트가 언마운트될 때 해당 함수가 실행된다.모든 것은 '클로저(Closure)'라는 개념과 연결되어 있다.
클로저: 자신이 생성될 시점의 환경을 기억하는 함수
기본적으로 함수는 실행을 마치고 나면 그 존재가 사라지게 되어있다. 이처럼 쓰이지 않는 메모리를 정리하는 것을 '가비지 컬렉팅(Garbage Collecting)'이라 한다.
그러나 hook
은 함수가 생성될 시점의 환경을 저장해뒀다가 끌어오기 때문에 함수는 사라지더라도 그 값을 유지할 수 있는 셈이다.