React는 명령형이 아닌 선언형 방식으로 UI를 조작한다.
명령형과 선언형은 어떻게 다른가?
-> 명령형 프로그래밍의 문제점들을 해결하기 위해 React가 만들어졌다.
React는 '상태(state)'의 변경에 따라 UI를 변경한다.
상태(state)는 말 그대로, 어떤 UI나 데이터 등의 상태를 말한다.
아래의 그림을 보자.
이렇게, textarea에 무언가 입력 중, 제출 중, 제출 성공or실패 등에 따라 UI가 바뀌어야 하는데, 이 때 필요한 것이 React의 useState를 통해 관리되는 '상태'이다.
useState을 사용하는 기본적인 형태는 아래와 같다.
const [state, setState] = useState(initialState);
useState 훅은 위에서 봤던 상태인 state, 그 상태를 변경해주는 함수인 setState를 구조분해할당으로 받아서 사용하고, 초기 값인 initialState를 설정해주어야 한다.
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<button onClick={handleClick}>
You pressed me {count} times
</button>
);
}
이 Counter 컴포넌트는 count라는 상태를 가지고 있으며, button을 클릭하면 setCount함수를 통해 count가 1 증가시키도록 작성되었다.
그렇다면, 이 useState는 어떻게 동작하는 걸까?
분명히, state가 컴포넌트 함수 내부에 있고, 리렌더링 된다면, 해당 함수가 다시 실행되면서 state도 새로 생성될텐데 어떻게 변화된 상태로 렌더링하는 걸까?
답은, 아래와 같다.
1. useState 훅을 통해 선언된 어떤 상태가 컴포넌트 내부가 아닌 React의 어딘가에서 상태들을 기억해 useState 훅이 호출된 순서대로 저장한다.
2. 컴포넌트가 리렌더링될 때, 동일한 순서로 훅을 호출하여, 알맞은 위치에 상태를 유지한다.
3. UI 등이 변경된 상태에 따라 렌더링된다.
state는 일반적인 변수와 비슷하지만, 다르다.
변수는 값이 변경되어도 아무 일도 일어나지 않지만, state가 변경될 때마다 컴포넌트를 리렌더링 한다.
그렇게 때문에, 리렌더링이 필요하지 않은 곳에 useState를 사용하게 되면 불필요한 리렌더링을 유발하기 때문에, 성능저하가 있을 수 밖에 없다.
useState를 꼭 필요한 부분에만 사용하고, 또한, state에 할당될 값도 과도한 리렌더링을 유발하지 않도록 신경써서 작성해야 한다.