State와 Hooks
React Hooks를 사용하여 함수형 컴포넌트에서 상태 관리와 부수 효과를 처리할 수 있다.
1️⃣ State (useState)
- State는 컴포넌트 내부에서 관리되는 동적인 데이터다.
- State가 변경되면 React는 자동으로 컴포넌트를 리렌더링한다.
- 일반 변수는 변경되어도 UI가 업데이트되지 않지만, State는 변경 시 자동으로 화면을 갱신한다.
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0); // 초기값 0
return (
<div>
<p>현재 카운트: {count}</p>
<button onClick={() => setCount(count + 1)}>증가</button>
<button onClick={() => setCount(count - 1)}>감소</button>
</div>
);
}
State의 특징
- 내부 데이터: 컴포넌트 내부에서만 관리
- 변경 가능:
setState함수를 통해 값 변경 - 추적: State 값이 변하면 UI가 자동으로 업데이트
- 비동기성:
setState는 즉시 반영되지 않고, 나중에 일괄 처리됨
State의 비동기성
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
console.log(count); // 아직 이전 값 출력
};
함수형 업데이트
- 이전 상태를 기반으로 새로운 상태를 계산할 때 사용
- 연속적인 상태 업데이트가 필요할 때 유용
const handleClick = () => {
setCount(prev => prev + 1);
setCount(prev => prev + 1);
setCount(prev => prev + 1);
// count는 3 증가
};
2️⃣ useEffect
useEffect는 렌더링 후 부수 효과(side effect)를 처리하는 Hook이다.- 부수 효과란 렌더링 과정과는 별개의 작업을 의미한다.
- 콘솔 로그 출력
- 서버에서 데이터 불러오기
- 타이머 사용
- DOM 직접 조작
- 외부 라이브러리 호출
import { useState, useEffect } from 'react';
function Timer() {
const [count, setCount] = useState(0);
// count가 변경될 때마다 실행
useEffect(() => {
console.log(`count가 ${count}로 변경되었습니다.`);
}, [count]); // 의존성 배열
return (
<div>
<p>현재 값: {count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}
의존성 배열
| 의존성 배열 | 실행 시점 |
|---|---|
[] (빈 배열) |
컴포넌트 마운트 시 1회만 실행 |
[state] |
해당 state가 변경될 때마다 실행 |
| 생략 | 매 렌더링마다 실행 (성능 저하 가능) |
마운트 시 1회만 실행
useEffect(() => {
console.log("컴포넌트가 마운트되었습니다.");
// 초기 데이터 로딩 등에 사용
}, []);
useEffect 무한 루프 주의
// ❌ 잘못된 예: 무한 루프 발생
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
setCount(prev => prev + 1); // count 변경
}, [count]); // count가 변경될 때마다 실행 → 무한 반복
return <p>{count}</p>;
}
// ✅ 올바른 예: 빈 배열로 1회만 실행
useEffect(() => {
setCount(prev => prev + 1);
}, []);
cleanup 함수
- useEffect에서 반환하는 함수는 컴포넌트가 언마운트되거나 다음 effect가 실행되기 전에 호출된다.
- 타이머 해제, 구독 취소 등에 사용
useEffect(() => {
const timer = setInterval(() => {
console.log('1초마다 실행');
}, 1000);
// cleanup 함수
return () => {
clearInterval(timer);
console.log('타이머 해제');
};
}, []);
3️⃣ 이벤트 처리
- React에서 이벤트는 camelCase로 작성한다 (
onClick,onChange). - 이벤트 핸들러는 함수 참조를 전달해야 한다.
- 인자가 있는 함수를 전달할 때는 화살표 함수로 감싸야 한다.
function Button() {
const handleClick = () => {
alert('버튼 클릭!');
};
return <button onClick={handleClick}>클릭</button>;
}
인자가 있는 이벤트 핸들러
function Greeting() {
const sayHello = (name) => {
alert(`안녕, ${name}!`);
};
// ❌ 잘못된 예: 렌더링 시 즉시 실행
// return <button onClick={sayHello('민서')}>인사</button>;
// ✅ 올바른 예: 클릭 시 실행
return <button onClick={() => sayHello('민서')}>인사</button>;
}
이벤트 객체 (e)
- 이벤트 핸들러는 자동으로 이벤트 객체
e를 받는다. e.target으로 이벤트가 발생한 요소에 접근할 수 있다.
function InputExample() {
const [text, setText] = useState('');
const handleChange = (e) => {
setText(e.target.value); // 입력값 가져오기
};
return (
<div>
<input type="text" onChange={handleChange} placeholder="입력하세요" />
<p>입력값: {text}</p>
</div>
);
}
이벤트 전파 (Bubbling)
- 이벤트는 자식에서 부모로 전파된다.
e.stopPropagation()으로 전파를 막을 수 있다.
function App() {
const handleCloseMenu = () => console.log("메뉴 닫힘");
const handleLogin = (e) => {
e.stopPropagation(); // 부모로 이벤트 전달 차단
console.log("로그인 클릭");
};
return (
<div onClick={handleCloseMenu}>
<button onClick={handleLogin}>로그인</button>
</div>
);
}
4️⃣ 조건부 렌더링
- 조건에 따라 다른 UI를 렌더링할 수 있다.
- 주로 삼항 연산자를 사용한다.
function LoginButton({ isLoggedIn }) {
return (
<div>
{isLoggedIn ? (
<button>로그아웃</button>
) : (
<button>로그인</button>
)}
</div>
);
}
조건부 렌더링 예제
function App() {
const [isLoggedIn, setIsLoggedIn] = useState(false);
return (
<div>
{isLoggedIn ? <p>환영합니다!</p> : <p>로그인해주세요</p>}
<button onClick={() => setIsLoggedIn(!isLoggedIn)}>
{isLoggedIn ? "로그아웃" : "로그인"}
</button>
</div>
);
}
&& 연산자를 이용한 조건부 렌더링
function Notification({ hasUnread }) {
return (
<div>
{hasUnread && <p>읽지 않은 메시지가 있습니다.</p>}
</div>
);
}'GDGoC > FrontEnd' 카테고리의 다른 글
| [Frontend] #06. React - 비동기 통신 (0) | 2026.05.06 |
|---|---|
| [Frontend] #05. React - React Router와 전역 상태 관리 (0) | 2026.05.06 |
| [Frontend] #03. React 기초 (0) | 2026.05.06 |
| [Frontend] #02. JavaScript (0) | 2026.05.06 |
| [Frontend] #01. HTML / CSS (0) | 2026.05.06 |