**state**는 리액트에서 컴포넌트의 상태를 나타내는 객체로, 컴포넌트의 동적인 데이터를 관리하고, 이 데이터가 변경될 때 컴포넌트를 다시 렌더링하는 역할을 합니다. state는 리액트 컴포넌트가 변경 가능한 값을 관리할 수 있도록 하며, 리액트의 핵심 개념 중 하나입니다.
1. state의 기본 개념
• **state**는 컴포넌트가 유지하고 있는 내부 데이터를 의미하며, 이 데이터는 시간이 지나면서 또는 사용자 상호작용에 따라 변경될 수 있습니다.
• state는 동적인 값을 저장하고, 그 값이 변경될 때마다 해당 컴포넌트와 그 자식 컴포넌트들이 자동으로 다시 렌더링됩니다.
• state는 컴포넌트 내부에서 관리되는 지역 상태이므로, 같은 컴포넌트 내에서만 사용할 수 있고 다른 컴포넌트와 직접적으로 공유되지 않습니다. 부모 컴포넌트나 외부로부터 전달받는 props와는 달리 컴포넌트 내부에서만 관리됩니다.
2. 함수형 컴포넌트에서의 state 관리: useState 훅
함수형 컴포넌트에서는 useState라는 리액트 훅을 사용해 상태를 관리합니다. useState 훅은 상태값과 해당 상태를 업데이트하는 함수를 반환합니다.
useState 기본 사용법:
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0); // 상태 초기값은 0
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
설명:
• useState(0): useState는 상태의 초기값을 받습니다. 이 예시에서는 0을 초기값으로 설정했습니다.
• [count, setCount]: useState는 배열을 반환합니다. 첫 번째 요소는 현재 상태(count), 두 번째 요소는 상태를 업데이트하는 함수(setCount)입니다.
• 상태 업데이트: setCount 함수를 호출하면 리액트가 상태를 업데이트하고, 컴포넌트는 다시 렌더링됩니다. 위 예시에서는 버튼을 클릭할 때마다 count가 1씩 증가하고, 그에 따라 UI가 업데이트됩니다.
3. state의 특징
1) 초기 상태
• 상태는 useState를 호출할 때 전달된 초기값으로 설정됩니다. 이 초기값은 컴포넌트가 처음 렌더링될 때만 사용되며, 이후로는 setState 함수로 상태를 변경합니다.
2) 상태 변경 시 리렌더링
• 상태가 변경되면 리액트는 해당 컴포넌트를 다시 렌더링합니다. 이때 리액트는 변경된 상태를 반영한 새로운 UI를 렌더링하고, 변경된 부분만 업데이트합니다.
function Example() {
const [text, setText] = useState('Hello');
return (
<div>
<p>{text}</p>
<button onClick={() => setText('Goodbye')}>Change Text</button>
</div>
);
}
• 위 코드에서 버튼을 클릭하면 text 상태가 “Goodbye”로 변경되고, UI가 다시 렌더링되어 텍스트가 업데이트됩니다.
3) 상태는 비동기적으로 업데이트
• 리액트는 성능 최적화를 위해 여러 상태 업데이트를 비동기적으로 처리할 수 있습니다. 연속된 상태 변경 요청은 리액트가 일괄 처리하여 한 번에 업데이트될 수 있습니다.
function Example() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
setCount(count + 2);
};
return <button onClick={handleClick}>Increment</button>;
}
• 위 코드에서 setCount가 두 번 호출되지만, 리액트는 이를 일괄 처리하여 한 번만 렌더링할 수 있습니다. 상태 변경은 비동기적으로 처리되어 성능을 최적화합니다.
4) 불변성 유지
• 리액트에서 상태는 불변성을 유지해야 합니다. 즉, 기존 상태를 직접 변경하지 않고 새로운 상태를 생성하여 업데이트해야 합니다. 이는 리액트가 상태 변경을 감지하고, 적절히 컴포넌트를 다시 렌더링하기 위함입니다.
function Example() {
const [items, setItems] = useState([1, 2, 3]);
const addItem = () => {
setItems([...items, 4]); // 상태를 복사한 후 새 아이템을 추가
};
return (
<div>
{items.map(item => <p key={item}>{item}</p>)}
<button onClick={addItem}>Add Item</button>
</div>
);
}
4. state와 props의 차이
• **state**는 컴포넌트 내부에서 관리되며, 동적인 데이터를 저장하고 관리하는 데 사용됩니다. 컴포넌트의 상태는 컴포넌트 자체에서 관리하며, 변경될 수 있습니다.
• **props**는 부모 컴포넌트가 자식 컴포넌트에게 전달하는 데이터입니다. props는 읽기 전용이며, 자식 컴포넌트에서는 변경할 수 없습니다.
비교:
특성 | state | props |
변경 가능 여부 | 컴포넌트 내에서 변경 가능 | 부모로부터 전달, 변경 불가 |
데이터 소유 | 컴포넌트 자체가 소유 | 부모 컴포넌트에서 전달됨 |
초기화 방식 | useState로 초기화 | 부모 컴포넌트에서 설정한 값 전달 |
5. 상태 관리의 패턴
컴포넌트 간 상태를 공유해야 할 때는 상태를 상위 컴포넌트로 끌어올려 상위 컴포넌트에서 상태를 관리하고, 그 상태를 props로 하위 컴포넌트에 전달하는 방식으로 처리합니다. 이 방식으로 여러 컴포넌트가 동일한 상태를 공유할 수 있습니다.
상태 끌어올리기 예시:
function Parent() {
const [count, setCount] = useState(0);
return (
<div>
<Child count={count} onIncrement={() => setCount(count + 1)} />
</div>
);
}
function Child(props) {
return (
<div>
<p>Count: {props.count}</p>
<button onClick={props.onIncrement}>Increment</button>
</div>
);
}
• 부모 컴포넌트에서 상태(count)를 관리하고, 그 상태를 자식 컴포넌트에 props로 전달하여 자식 컴포넌트에서 상태를 사용할 수 있게 합니다.
• 자식 컴포넌트에서 콜백 함수를 호출하여 부모의 상태를 업데이트할 수 있습니다.
결론
• 함수형 컴포넌트에서 state는 컴포넌트의 동적인 데이터를 관리하고, 상태가 변경될 때마다 UI를 자동으로 다시 렌더링하는 중요한 개념입니다.
• useState 훅을 사용하여 상태를 정의하고, 상태 업데이트 함수로 상태를 변경할 수 있습니다.
• 상태는 직접 수정할 수 없으며, 반드시 setter 함수를 통해 변경해야 합니다.
• state는 각 컴포넌트 내에서 관리되는 독립적인 데이터이지만, 상위 컴포넌트를 통해 여러 컴포넌트 간 상태를 공유할 수 있습니다.
'React' 카테고리의 다른 글
[React] 컴포넌트 라이프사이클 (1) | 2024.09.13 |
---|---|
[React] 리액트 상태(State)와 자바스크립트의 비동기 차이점 (1) | 2024.09.13 |
[React] Props (0) | 2024.09.13 |
[React] 컴포넌트 개념과 역할 (0) | 2024.09.12 |
[React] JSX란 무엇인가? (0) | 2024.09.12 |