React에서 상태 관리를 더 효율적으로 할 수 있는 훅(Hook) 중 하나가 바로 useReducer입니다. 이 훅은 상태 관리가 복잡해질 때 useState의 대체품으로 유용하게 사용될 수 있습니다. useReducer는 주로 여러 상태 값이나 복잡한 상태 로직을 다룰 때 그 유용성을 발휘합니다.
이번 글에서는 useState와 useReducer를 활용한 다양한 상태 관리 예제를 소개하고, 이를 통해 어떻게 상태를 더 깔끔하게 관리할 수 있는지 알아보겠습니다.
useState와 useReducer 비교
1. useState 사용법
useState는 간단한 상태 값을 관리할 때 사용됩니다. 아래 예제는 카운터를 관리하는 간단한 React 컴포넌트입니다.
import { useState } from "react";
const Counter = () => {
const [count, setCount] = useState(0); // 상태 변수 'count'와 이를 업데이트할 함수 'setCount'
const changeCount = e => setCount(count + Number(e.target.innerText)); // 버튼의 텍스트를 숫자로 변환하여 카운트 업데이트
return (
<>
<h1>현재 카운트 값: {count}</h1>
<button onClick={changeCount}>+1</button>
<button onClick={changeCount}>-1</button>
</>
);
};
const App = () => <Counter />;
export default App;
위 코드에서는 useState를 사용하여 count 상태를 관리하고, 버튼을 클릭할 때마다 상태 값을 변경합니다.
2. useReducer 사용법
useReducer는 상태 변경 로직이 복잡할 때 유용한 훅입니다. 상태와 액션을 받아 새로운 상태를 반환하는 리듀서(reducer) 함수를 사용하여 상태를 관리합니다. useReducer는 두 개의 반환값을 가집니다:
- 상태(현재 상태 값)
- 디스패치 함수(액션을 리듀서에 전달해 상태를 업데이트하는 함수)
import { useReducer } from "react";
// 리듀서 함수 정의: 상태와 액션을 받아 새로운 상태를 반환
function reducer(state, action) {
switch (action.type) {
case "PLUSONE":
return { count: state.count + 1 };
case "MINUSONE":
return { count: state.count - 1 };
default:
return state;
}
}
const Counter = () => {
const [state, dispatch] = useReducer(reducer, { count: 0 }); // 상태 초기화
return (
<>
<h1>현재 카운트 값: {state.count}</h1>
<button onClick={() => dispatch({ type: "PLUSONE" })}>하나 증가</button>
<button onClick={() => dispatch({ type: "MINUSONE" })}>하나 감소</button>
</>
);
};
const App = () => <Counter />;
export default App;
위 코드에서는 useReducer를 사용해 count 상태를 관리하고, 액션 타입을 PLUSONE, MINUSONE으로 정의하여 카운트를 증가시키거나 감소시킬 수 있습니다.
3. 추가적인 액션과 동적 값 처리
다음 예제에서는 useReducer를 활용해 숫자 값을 동적으로 조정할 수 있도록 구현해 보겠습니다. 버튼을 클릭하면 1 또는 5를 더하거나 뺄 수 있습니다.
import { useReducer } from "react";
// 리듀서 함수 정의: action.value에 따라 카운트 값을 변화시킴
function reducer(state, action) {
switch (action.type) {
case "PLUS":
return { count: state.count + action.value };
case "MINUS":
return { count: state.count - action.value };
default:
return state;
}
}
const Counter = () => {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<>
<h1>현재 카운트 값: {state.count}</h1>
<button onClick={() => dispatch({ type: "PLUS", value: 1 })}>하나 증가</button>
<button onClick={() => dispatch({ type: "MINUS", value: 1 })}>하나 감소</button>
<button onClick={() => dispatch({ type: "PLUS", value: 5 })}>다섯 더하기</button>
<button onClick={() => dispatch({ type: "MINUS", value: 5 })}>다섯 빼기</button>
</>
);
};
const App = () => <Counter />;
export default App;
여기서는 버튼을 클릭할 때마다 value 값을 동적으로 PLUS 또는 MINUS 액션에 전달하여 count 값을 1 또는 5씩 증가시키거나 감소시킵니다.
useEffect와 useReducer의 결합
useEffect 훅은 컴포넌트의 생애주기(lifecycle)에 맞춰 특정 작업을 실행할 수 있게 해주는 훅입니다. 상태 값이 변경될 때마다 특정 작업을 수행하거나, 컴포넌트가 언마운트될 때 클린업 작업을 할 수 있습니다. useReducer와 함께 사용할 때도 유용합니다.
아래 예제에서는 이름과 별명 상태를 useReducer로 관리하고, useEffect를 통해 상태가 변경될 때마다 로그를 출력합니다.
import { useEffect, useReducer } from "react";
// 리듀서 함수 정의: 'name'과 'nickname' 값을 처리
function reducer(state, action) {
switch (action.type) {
case "name":
case "nickname":
return { ...state, [action.type]: action.value };
default:
return state;
}
}
function Info() {
const [state, dispatch] = useReducer(reducer, { name: '', nickname: '' });
useEffect(() => {
console.log("name 상태변수가 변경되었습니다.");
console.log({ name: state.name, nickname: state.nickname });
return () => console.log("cleanup", state.name);
}, [state.name]); // 'name'이 변경될 때마다 실행
return (
<>
<div>
<p>이름: {state.name}</p>
<p>별명: {state.nickname}</p>
</div>
<div>
<p>이름: <input type="text" value={state.name} onChange={e => dispatch({ type: "name", value: e.target.value })} /></p>
<p>별명: <input type="text" value={state.nickname} onChange={e => dispatch({ type: "nickname", value: e.target.value })} /></p>
</div>
</>
);
}
const App = () => <Info />;
export default App;
위 예제에서는 이름과 별명 상태를 useReducer로 관리하고, useEffect를 사용해 상태 변경을 추적합니다. 상태가 변경될 때마다 콘솔에 로그를 출력하고, 컴포넌트가 언마운트될 때 클린업 작업을 수행합니다.
useReducer는 상태 변화가 복잡해지거나 여러 상태를 다룰 때 useState보다 더 나은 선택이 될 수 있습니다. 리듀서 함수와 액션을 활용하여 상태를 업데이트하고, useEffect를 통해 상태 변경을 추적하거나 클린업 작업을 할 수 있습니다. useReducer를 잘 활용하면 React 컴포넌트의 상태 관리가 훨씬 깔끔하고 효율적으로 개선될 수 있습니다.
*생성형 AI 활용한 클라우드&보안 전문가 양성캠프 과정의 교육내용 정리 자료입니다
'코딩 > 리액트' 카테고리의 다른 글
[새싹 성동 2기] Context API와 useContext 훅을 사용하여 테마 적용하기 (1) | 2024.12.06 |
---|---|
[새싹 성동 2기] useMemo, useCallback, React.memo 활용법 (1) | 2024.12.06 |
[새싹 성동 2기] 리액트 앱에서 국가와 국기 정보를 출력하는 방법 (1) | 2024.11.19 |
[새싹 성동 2기] React에서 useRef 예제 및 활용법 (1) | 2024.11.19 |
[새싹 성동 2기] React에서 Hooks (useState와 useEffect) 사용하기 (0) | 2024.11.19 |