useState — React 상태 관리의 시작
이 토픽을 마치면
useState로 상태를 만들고 업데이트하는 방법, 그리고 리렌더링이 일어나는 원리를 이해하게 됩니다.
일반 변수로는 안 됩니다
function Counter() {
let count = 0;
function handleClick() {
count += 1;
console.log(count); // 1, 2, 3... 올라감
}
return <button onClick={handleClick}>{count}</button>;
// 화면에는 항상 0
}count는 올라가지만 화면은 바뀌지 않습니다. React는 일반 변수가 바뀌는 걸 감지하지 못합니다. 화면을 업데이트하려면 React에게 "상태가 바뀌었다"고 알려줘야 합니다.
useState
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
{count}
</button>
);
}useState(0)은 두 가지를 반환합니다:
count: 현재 상태 값setCount: 상태를 변경하는 함수
setCount를 호출하면 React가 컴포넌트를 리렌더링합니다. 새로운 count 값으로 화면이 다시 그려집니다.
상태 업데이트는 비동기입니다
function handleClick() {
setCount(count + 1);
console.log(count); // 아직 이전 값!
}setCount를 호출해도 count가 즉시 바뀌지 않습니다. 다음 렌더링에서 새 값이 반영됩니다.
이전 값을 기반으로 업데이트할 때는 함수형 업데이트를 씁니다:
setCount(prev => prev + 1);prev에 현재 최신 값이 들어옵니다. 여러 번 연속 호출해도 정확합니다:
setCount(prev => prev + 1);
setCount(prev => prev + 1);
setCount(prev => prev + 1);
// count가 3 증가객체와 배열 상태
const [user, setUser] = useState({ name: "Alice", age: 25 });
// 나쁜 예: 직접 수정
user.age = 26; // React가 변화를 감지 못함
setUser(user); // 같은 참조라 리렌더링 안 됨
// 좋은 예: 새 객체 생성
setUser({ ...user, age: 26 });React는 참조가 바뀌었는지를 확인합니다. 기존 객체를 수정하면 참조가 같아서 변화를 감지하지 못합니다. Spread 연산자로 새 객체를 만들어야 합니다.
배열도 마찬가지입니다:
const [items, setItems] = useState(["a", "b"]);
// 추가
setItems([...items, "c"]);
// 삭제
setItems(items.filter(item => item !== "b"));
// 수정
setItems(items.map(item => item === "a" ? "A" : item));push, splice 같은 원본 변경 메서드는 쓰지 않습니다.
useState 여러 개
const [name, setName] = useState("");
const [age, setAge] = useState(0);
const [isActive, setIsActive] = useState(false);관련 없는 상태는 따로 선언합니다. 항상 같이 바뀌는 값들은 하나의 객체로 묶을 수도 있습니다.
핵심
useState는 React 컴포넌트에 상태를 추가하고,setState호출 시 리렌더링합니다. 상태 업데이트는 비동기이므로, 이전 값 기반 업데이트는 함수형(prev => ...)을 쓰세요. 객체/배열 상태는 원본을 수정하지 말고 새 것을 만들어야 합니다.