이전까지는 컴포넌트의 상태관리를 하기 위해서는 클래스 컴포넌트를 사용해야만 했습니다.
하지만 React Hook은 함수 컴포넌트에서도 상태관리를 가능하게 합니다.
또한
리액트 공식문서에 따르면, 클래스는 '코드의 최소화를 힘들게 만들고, 핫 리로딩을 깨지기 쉽고 신뢰할 수 없게 만듭니다'.
여러모로 클래스 컴포넌트보다 Reack Hook을 사용한 함수 컴포넌트가 더 낫다는 말인 것 같습니다.
상태관리를 가능하게 하는 State Hook, Side Effect를 가능하게 하는 Effect Hook으로 나누어 생각해보겠습니다.
React 컴포넌트가 화면에 렌더링된 이후에 비동기로 처리되어야 하는 부수적인 효과들을 흔히 Side Effect라 합니다.
State Hook, 즉 useState는 함수 컴포넌트에서 상태관리를 가능하게 합니다.
사용법은 다음과 같습니다. 먼저 useState를 'react'로부터 받아오면 됩니다.
import React, { useState } from 'react';
위와 같이 useState를 받아왔다면, 이젠 실제적인 사용법을 알아보겠습니다.
useState는 현재의 state 값과 이 값을 업데이트하는 함수를 쌍으로 제공합니다.
구조분해할당을 사용하여 name 변수와 setName 함수를 선언해주면 상태와 함수를 보다 편하게 사용할 수 있습니다.
변수와 함수의 이름은 사용자 지정이지만, 암묵적인 룰이 있는 것 같습니다. 변수명을 something이라 한다면, 함수명은 setSomething이라고 짓습니다. 하지만 법칙은 아닙니다.
// 암묵적인 룰
// const [something, setSomething] = useState();
const [name, setName] = useState();
관리할 상태의 이름으로 name, 상태를 관리할 함수의 이름으로 setName을 지정했습니다.
useState 메서드 사용 시에 상태의 초기값을 줄 수 있는데, useState 메서드의 인자로 원하는 값을 지정해주면 그 값이 관리할 상태의 초기값이 됩니다.
const [name, setName] = useState('banny');
name 상태의 초기값으로 'banny'를 지정했습니다.
또한, 다음과 같이 여러 개의 state 변수를 선언할 수 있습니다.
const [age, setAge] = useState(20);
const [job, setJob] = useState('developer');
클래스 컴포넌트에서는 this.state를 통해 상태에 접근해야 했습니다.
하지만 함수 컴포넌트에서는 상태에 직접 접근할 수 있습니다. 상태와 함수 선언 시에 구조분해할당(destructing)을 해주었기 때문에 더 쉽게 접근할 수 있습니다.
위에서 선언한 상태를 사용해보겠습니다.
<p>제 이름은 {name}입니다.</p>
<p>제 나이는 {age}세 입니다.</p>
<p>제 직업은 {job}입니다.</p>
그렇다면 상태를 갱신하는 함수는 어떻게 사용할 수 있을까요?
아래의 예시에서는 버튼 클릭 시 상태를 갱신하는 함수가 실행됩니다.
<button onClick={() => setName(name + "가 아니라 반석쓰")}>이름 변경</button>
<button onClick={() => setAge(age + 1)}>
{age >= 30 ? <span>그만하세요</span> : <span>나이 올리기</span>}
</button>
<button onClick={() => setJob(job + "!")}>자부심 추가</button>
상태 갱신이 수행되는 화면입니다.
state 갱신함수는 기존의 state를 기억하네요.
이와 같이 useState 메서드를 사용하여 state 변수와 state 갱신함수를 선언하고, 함수 컴포넌트 내부에서도 상태를 관리할 수 있습니다 😆😆
Effect Hook, 즉 useEffect는 함수 컴포넌트 내에서 Side Effect를 수행할 수 있게 해줍니다.
리액트 공식문서에 따르면, "useEffect Hook을 componentDidMount와 componentDidUpdate, componentWillUnmount가 합쳐진 것으로 생각해도 좋습니다."
사용법은 useState의 경우와 같습니다. useState와 같은 방법으로 react에서 받아옵니다.
import React, { useState, useEffect } from 'react';
기억할 것은, useState 메서드는 렌더링 이후에 매번 실행된다는 것입니다.
useEffect메서드에는 첫 번째 인자로 수행하고자 하는 함수가 콜백함수로 들어갑니다.
두 번째 인자로는 상태 변수가 들어가는데, 이것은 optional합니다.
그렇다면 두 번째 인자를 주었을 때와 주지 않았을 때를 나누어 살펴보겠습니다.
useEffect(() => {
console.log("useEffect가 실행됩니다.");
});
두 번째 인자를 지정하지 않을 경우에는, 많은 상태 중 어느 하나라도 변경되면 useEffect 메서드가 실행됩니다. 백문이 불여일견. 콘솔을 통해 확인해볼 수 있습니다.
이번에는 두 번째 인자를 지정해주었습니다. 위에서 언급했듯이, 두 번째 인자로는 상태 변수가 들어갑니다.
그리고 지정된 상태가 갱신이 될 때만 useEffect 메서드는 실행됩니다.
age라는 상태를 두 번째 인자로 지정했습니다. '나이 올리기' 버튼을 클릭할 때만 useEffect가 실행됩니다. 콘솔을 통해 확인하시죠!
useEffect(() => {
console.log("useEffect가 실행됩니다.");
}, [age]);
두 번째 인자로 여러 개의 상태를 지정할 수도 있습니다. 그러면 해당 상태들이 갱신될 때에만 useEffect 메서드가 실행됩니다.
useEffect(() => {
console.log("useEffect가 실행됩니다.");
}, [age, isHuman]);