React는 컴포넌트를 기반으로 동적인 UI를 구축하는 라이브러리입니다. 이때 중요한 개념 중 하나가 바로 **상태(state)**입니다. 상태는 컴포넌트 내부에서 데이터나 UI의 변화를 추적하고 관리하는 데 사용됩니다. React에서는 상태를 관리하기 위해 여러 가지 방법을 제공하지만, 가장 기본적이고 널리 사용되는 방법은 바로 useState 훅입니다.
이번 글에서는 React에서 useState 훅을 어떻게 사용하는지, 기본적인 사용법부터 고급 활용까지 단계별로 살펴보겠습니다.
useState란 무엇인가?
useState는 React의 함수형 컴포넌트에서 상태를 관리할 수 있도록 도와주는 훅입니다. React는 컴포넌트가 리렌더링될 때마다 상태 값을 추적하는데, useState는 상태를 정의하고, 해당 상태를 갱신할 수 있는 함수를 반환합니다.
useState 훅은 다음과 같이 사용합니다:
const [state, setState] = useState(initialValue);
- state: 현재 상태 값
- setState: 상태를 업데이트하는 함수
- initialValue: 상태의 초기 값
이 간단한 패턴을 통해 함수형 컴포넌트 내에서 상태를 선언하고 업데이트할 수 있게 됩니다.
useState의 기본 사용법
1. 간단한 상태 값 관리
가장 기본적인 사용법은 상태를 boolean, number, string 등 단순한 데이터 타입으로 설정하는 것입니다.
import React, { useState } from 'react';
function Counter() {
// 초기 상태 값은 0
const [count, setCount] = useState(0);
const increment = () => setCount(count + 1);
const decrement = () => setCount(count - 1);
return (
<div>
<p>현재 카운트: {count}</p>
<button onClick={increment}>증가</button>
<button onClick={decrement}>감소</button>
</div>
);
}
export default Counter;
위 코드에서 useState(0)은 count라는 상태 변수를 0으로 초기화하고, setCount는 그 값을 변경할 수 있는 함수입니다. 버튼을 클릭할 때마다 상태가 변경되며 컴포넌트가 리렌더링됩니다.
2. 상태 업데이트 함수
setState는 상태를 변경하는 함수입니다. 상태 업데이트 함수는 새로운 상태 값을 인자로 받아 상태를 변경하며, 리렌더링을 트리거합니다. 상태 변경 시, 반드시 이전 상태를 기반으로 새로운 상태를 계산해야 하는 경우가 많습니다. 이때는 함수형 업데이트 방식으로 상태를 업데이트합니다.
const [count, setCount] = useState(0);
const increment = () => {
setCount(prevCount => prevCount + 1); // 이전 상태를 기반으로 계산
};
위 예시에서는 setCount 함수에 콜백을 전달하여 이전 상태(prevCount)를 기반으로 새로운 값을 계산하고 있습니다. 이렇게 하면 상태 업데이트가 안전하게 이루어집니다.
useState의 고급 활용법
1. 객체나 배열 상태 관리
useState는 원시 값만 다룰 수 있는 것이 아닙니다. 객체나 배열과 같은 복잡한 데이터 구조도 상태로 관리할 수 있습니다. 이 경우, 상태를 업데이트할 때 주의할 점이 있습니다. 객체나 배열의 상태를 업데이트할 때는 불변성을 지켜야 합니다.
객체 상태 관리
import React, { useState } from 'react';
function UserInfo() {
const [user, setUser] = useState({ name: '홍길동', age: 30 });
const updateName = () => {
setUser(prevUser => ({ ...prevUser, name: '김철수' }));
};
const updateAge = () => {
setUser(prevUser => ({ ...prevUser, age: prevUser.age + 1 }));
};
return (
<div>
<p>이름: {user.name}</p>
<p>나이: {user.age}</p>
<button onClick={updateName}>이름 변경</button>
<button onClick={updateAge}>나이 증가</button>
</div>
);
}
export default UserInfo;
위 예시에서는 user라는 객체를 상태로 관리하고 있습니다. 상태를 업데이트할 때는 객체를 복사한 후 필요한 필드를 수정하여 새로운 객체를 만들어야 합니다. ...prevUser는 객체를 복사하는 스프레드 연산자입니다.
배열 상태 관리
배열 상태를 업데이트할 때도 마찬가지로 불변성을 유지해야 하므로, 새로운 배열을 생성하여 상태를 갱신합니다.
import React, { useState } from 'react';
function TodoList() {
const [todos, setTodos] = useState([]);
const [newTodo, setNewTodo] = useState('');
const addTodo = () => {
setTodos(prevTodos => [...prevTodos, newTodo]);
setNewTodo(''); // 입력 필드 초기화
};
return (
<div>
<input
type="text"
value={newTodo}
onChange={(e) => setNewTodo(e.target.value)}
/>
<button onClick={addTodo}>할 일 추가</button>
<ul>
{todos.map((todo, index) => (
<li key={index}>{todo}</li>
))}
</ul>
</div>
);
}
export default TodoList;
이 예시에서는 todos라는 배열을 상태로 관리하고, 새로운 할 일을 추가할 때 setTodos를 사용하여 기존 배열을 복사한 후 새로운 항목을 추가하는 방식으로 상태를 갱신합니다.
2. 상태의 초기 값 계산
useState에서 상태의 초기값을 계산할 때, 값이 동적으로 결정되는 경우가 있을 수 있습니다. 이때 초기값을 계산하는 함수를 사용할 수 있습니다.
import React, { useState } from 'react';
function ExpensiveComponent() {
const [value, setValue] = useState(() => {
const initialValue = computeExpensiveValue();
return initialValue;
});
return (
<div>
<p>계산된 값: {value}</p>
</div>
);
}
function computeExpensiveValue() {
console.log('값을 계산 중...');
return 42;
}
export default ExpensiveComponent;
위 코드에서 useState의 초기값으로 함수를 전달하면, 컴포넌트가 렌더링될 때 초기값 계산이 한 번만 수행됩니다. 이를 통해 불필요한 계산을 방지할 수 있습니다.
useState의 주의사항과 팁
1. 상태 업데이트는 비동기적
setState는 비동기적으로 상태를 업데이트합니다. 즉, 상태가 업데이트된 직후에 바로 그 값을 참조할 수 없습니다. 상태 업데이트가 완료되기 전에 그 값을 사용하려면, 렌더링 후에 반영된 상태 값을 확인해야 합니다.
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
console.log(count); // 이전 count 값이 출력됨
};
위 코드에서 setCount가 호출되고 나서 console.log(count)가 실행되면, count는 아직 이전 값으로 출력됩니다. 이는 상태가 비동기적으로 업데이트되기 때문입니다.
2. 불변성 유지
useState를 사용할 때 불변성을 지키는 것이 매우 중요합니다. 상태를 직접 수정하는 대신 항상 상태의 복사본을 만들어서 변경해야 합니다. 이는 리액트의 성능 최적화와 리렌더링을 정확하게 처리하기 위한 핵심 원칙입니다.
결론
useState 훅은 React에서 상태를 관리하기 위한 가장 기본적이고 강력한 도구입니다. 이를 통해 컴포넌트의 상태를 선언하고, 해당 상태를 업데이트하면서 동적인 UI를 구축할 수 있습니다. 기본적인 사용법을 넘어서 객체나 배열 상태를 관리하는 방법, 초기값 계산 최적화 등 다양한 활용 방법을 배워봤습니다.
React의 상태 관리에 대한 이해를 높이면, 더욱 효율적이고 깔끔한 코드를 작성할 수 있습니다. useState는 리액트의 핵심 개념이므로, 이를 잘 활용할 수 있다면 더 복잡한 상태 관리도 쉽게 처리할 수 있을 것입니다.
'React' 카테고리의 다른 글
React에서 useEffect 훅 사용법 (0) | 2024.12.09 |
---|---|
React에서 조건부 렌더링 사용하기 (0) | 2024.12.09 |
React 상태(State)란 무엇인가? (0) | 2024.12.09 |
React 함수형 컴포넌트 vs 클래스형 컴포넌트 (0) | 2024.12.09 |
React Props를 통한 데이터 전달 (0) | 2024.12.09 |