Frontend

[React] useState 사용해보기

min_ee 2025. 6. 23. 15:15

멘토님께서 React에서 제공하는 useHook 중 몇 개를 써보았는지 물어보시며

한번씩 다 써보는걸 추천하셨다.

 

그래서 하나씩 직접 써보고 정리해보기로 했다.🙂

 

React에서 가장 자주 사용되는 Hook인 useState컴포넌트의 상태를 관리할 때 사용된다.

상태 관리에도 여러 종류가 있지만 나는 숫자, 객체, 배열의 상태를 다뤄보았다.

 

useState란?

useSate는 React에서 컴포넌트의 상태(state)를 저장하고 갱신할 수 있는 Hook이다.

const [state, setState] = useState(초기값);

여기서 state는 현재 상태 값, setState는 상태를 업데이트하는 함수이다.

 

실습해보기

숫자 상태 관리

const Counter = () => {
	const [count, setCount] = useState<number>(0);

	const increase = () => setCount((prev) => prev + 1);
	const decrease = () => setCount((prev) => prev - 1);
	return (
		<section>
			<h2>Counter</h2>
			<p>{count}</p>
			<div>
				<button onClick={decrease}>- 감소</button>
				<button onClick={increase}>+ 증가</button>
			</div>
		</section>
	);
};

이전 값에 의존 하는 경우 prev => prev + 1 형태로 함수형 업데이트를 사용하는 것이 안전하다.

 

객체 상태 관리

const UserInfo = () => {
	const [user, setUser] = useState({ name: "민이", age: 30 });

	const changeName = () => {
		setUser({ ...user, name: "치즈" });
	};
	const increase = () => {
		setUser((prev) => ({ ...prev, age: prev.age + 1 }));
	};
	const decrease = () => {
		setUser((prev) => ({ ...prev, age: prev.age - 1 }));
	};

	return (
		<section>
			<h2>UserInfo</h2>
			<h3>이름: {user.name}</h3>
			<h3>나이: {user.age}</h3>
			<div>
				<button onClick={changeName}>이름 변경</button>
				<button onClick={decrease}>- 감소</button>
				<button onClick={increase}>+ 증가</button>
			</div>
		</section>
	);
};

객체상태는 추가, 수정의 경우 반드시 spread연산자(...)를 이용해 기존 상태를 복사하고 일부만 바꿔야한다.

직접 수정할 경우 리렌더링이 되지않기 때문에 조심!(상태의 참조가 바뀌어야 리렌더링이 됨)

 

배열 상태 관리

const TodoList = () => {
	const [todos, setTodos] = useState<string[]>([
		"알고리즘 풀기",
		"치즈 산책 가기",
		"개념 공부",
	]);

	const addTodo = () => {
		setTodos((prev) => [...prev, `새로운 할일 ${prev.length + 1}`]);
	};

	const removeFirst = () => {
		setTodos((prev) => prev.slice(1)); // 제일 첫 항목 제거
	};

	return (
		<section>
			<h2>할 일 목록</h2>
			<ul>
				{todos.map((todo, index) => (
					<li key={index}>{todo}</li>
				))}
			</ul>
			<div>
				<button onClick={addTodo}>할 일 추가</button>
				<button onClick={removeFirst}>첫 항목 제거</button>
			</div>
		</section>
	);
};

배열도 마찬가지로 원본을 직접 수정하지 않고

spread 연산자를 사용하거나 filter, slice를 활용해 새로운 배열을 만들어야한다.

 

주의사항

React는 상태 변경을 감지할 때 객체나 배열의 참조를 비교하기 때문에, 반드시 새로운 객체나 배열을 만들어 전달해야한다!

// 잘못된 방식
count++;
todos.push("new task");
user.name = "치즈";

// 올바른 방식
setCount(prev => prev + 1);
setTodos([...todos, "new task"]);
setUser({ ...user, name: "치즈" });

 

정리하며

예제를 통해 useState를 직접 사용해보니

불변성을 유지하는 것이 핵심이라는 걸 다시 한 번 느꼈다.

 

또한 상태 업데이트 시 prev => ... 형태의 함수형 업데이트를 활용하면

예상치 못한 렌더링 문제나 비동기성 이슈를 줄일 수 있다는 것도 알게 되었다.

 

참고 페이지

https://react.dev/reference/react/useState

 

useState – React

The library for web and native user interfaces

react.dev