
1. useReducer 이해하기
리액트 훅 useReducer를 이용하면 컴포넌트에서 상태 변화 코드를 쉽게 분히 할 수 있습니다.
1. 실습 준비하기
// 2025-01-06 7장 useReducer와 상태관리리
// src/App.js
// 1.1.1 useReducer이해하기기
import "./App.css";
import Header from "./component/Header";
import TodoEditor from "./component/TodoEditor";
import TodoList from "./component/TodoList";
import { useState, useRef } from "react";
import TestComp from "./component/TestComp";
const mockTodo = [
{
id: 0,
isDone: false,
content: "React 공부하기",
createdDate: new Date().getTime(),
},
{
id: 1,
isDone: false,
content: "빨래 널기",
createdDate: new Date().getTime(),
},
{
id: 2,
isDone: false,
content: "노래 연습하기",
createdDate: new Date().getTime(),
},
];
function App() {
const idRef = useRef(3);
const [todo, setTodo] = useState(mockTodo);
const onCreate = (content) => {
const newItem = {
id: idRef.current,
content,
isDone: false,
createdDate: new Date().getTime(),
};
setTodo([newItem, ...todo]);
idRef.current += 1;
};
const onUpdate = (targetId) => {
setTodo(
todo.map((it) =>
it.id === targetId ? { ...it, isDone: !it.isDone } : it
)
);
};
const onDelete = (targetId) => {
setTodo(todo.filter((it) => it.id !== targetId));
};
return (
<div className="App">
<TestComp />
<Header />
<TodoEditor onCreate={onCreate} />
<TodoList todo={todo} onUpdate={onUpdate} onDelete={onDelete} />
</div>
);
}
export default App;
// 2025-01-06 7장 useReducer와 상태관리리
// src/component/TestComp.js
// 1.1.1 useReducer이해하기기
import { useState } from "react";
function TestComp(){
const [count, setCount] = useState(0);
const onIncrease = () => {
setCount(count + 1);
};
const onDecrease = () => {
setCount(count - 1);
};
return (
<div>
<h4> 테스트 컴포넌트 </h4>
<div>
<bold>{count}</bold>
</div>
<div>
<button onClick = {onIncrease}>+</button>
<button onClick = {onDecrease}>-</button>
</div>
</div>
)
}
export default TestComp;

2. 상태 변환 코드란?
상태변환 코드란 State값을 변경하는 코드입니다.
(앞에 만든 onIncrease와 onDecrease가 상태변환 코드라고 할 수 있습니다.)
컨포넌트에서 상태변환코드를 분리한가는 것은 컨포넌트 내부에 작성한 코드를 외부에 작성한다는 뜻입니다.
useState를 이용해 만들면 상태 변환 코드를 분리 할 수 없습니다. 때문에 useReducer을 이용해서 외부에 작성합니다.
3. useReducer의 기본 사용법
useReducer은 리액트 컨포넌트에서 State를 관리하는 리액트의 훅입니다.
State관리를 컨포넌트 외부에서 할 수 있기 때문에 상태변화 코드를 분리 할 수 있습니다.
파일로 분리가 가능하기 때문에 컴포넌트 내부가 훨씬 간결해 집니다.
// src/component/TestComp.js
// 1.3.1 useREducer의 기본 사용법
import { useReducer } from "react";
function reducer(state, action) {
switch (action.type){
case "INCREASE":
return state + action.data;
case "DECREASE":
return state - action.data;
case "INIT":
return 0;
default:
return state;
}
}
function TestComp(){
const [count, dispatch] = useReducer(reducer ,0);
// dispatch: 상태변화가 필요할 때 촉발하는 함수, dispatch에서 인수로 전달되는 값에 State변화 값이 들어 있고 이를 action객체라고 합니다.
// dispatch가 실행되면 함수 reducer이 실행되는데, 이 함수가 반환하는 값이 새로운 State값이 됩니다.
// dispatch 호출 -> reducer호출 -> State값 업데이트트
return (
<div>
<h4> 테스트 컴포넌트 </h4>
<div>
<bold>{count}</bold>
</div>
<div>
<button onClick={() => dispatch({type: "INCREASE", data: 1 })}>
+
</button>
<button onClick={() => dispatch({type: "DECREASE", data: 1 })}>
-
</button>
<button onClick={() => dispatch({type: "INIT"})}>
0으로 초기화
</button>
</div>
</div>
)
}
export default TestComp;

2. [ 할 일 관리 ]앱 업그레이드
1. useState를 useReducer로 바꾸기
실무에서는 State가 복작하지 않으면 useState를 사용하지만, 그렇지 않으면 useReducer을 사용합니다.
useState를 삭제합니다. (아직 실행x)
// src/App.js
// 2.1 할일 관리 앱 업테이트
import "./App.css";
import Header from "./component/Header";
import TodoEditor from "./component/TodoEditor";
import TodoList from "./component/TodoList";
import { useReducer, useRef } from "react";
import TestComp from "./component/TestComp";
const mockTodo = [
{
id: 0,
isDone: false,
content: "React 공부하기",
createdDate: new Date().getTime(),
},
{
id: 1,
isDone: false,
content: "빨래 널기",
createdDate: new Date().getTime(),
},
{
id: 2,
isDone: false,
content: "노래 연습하기",
createdDate: new Date().getTime(),
},
];
function useReducer(state, action) {
return state;
}
function App() {
const idRef = useRef(3);
const [todo, dispatch] = useReducer(useReducer, mockTodo);
const onCreate = (content) => {
idRef.current += 1;
};
const onUpdate = (targetId) => {
};
const onDelete = (targetId) => {
};
return (
<div className="App">
<TestComp />
<Header />
<TodoEditor onCreate={onCreate} />
<TodoList todo={todo} onUpdate={onUpdate} onDelete={onDelete} />
</div>
);
}
export default App;
2. Create: 할일 아이템 추가하기
3. Update: 할 일 아이템 수정하기
4. Delete: 할 일 삭제 구현하기
onCreate에서 dispatch를 호출하고, 인수로 할 일 정보를 담은 action객체를 전달합니다.
// src/App.js
// 2.3 Update
import "./App.css";
import Header from "./component/Header";
import TodoEditor from "./component/TodoEditor";
import TodoList from "./component/TodoList";
import { useReducer, useRef } from "react";
const mockTodo = [
{
id: 0,
isDone: false,
content: "React 공부하기",
createdDate: new Date().getTime(),
},
{
id: 1,
isDone: false,
content: "빨래 널기",
createdDate: new Date().getTime(),
},
{
id: 2,
isDone: false,
content: "노래 연습하기",
createdDate: new Date().getTime(),
},
];
function reducer(state, action) {
switch (action.type){
case "CREATE":{
return [action.newItem, ...state]
}
case "UPDATE": {
return state.map((it) =>
it.id === action.targetId
?{
...it,
isDone: !it.isDone,
}
: it
);
}
case "DELETE":{
return state.filter((it) => it.id !== action.targetId);
}
default:
return state;
}
}
function App() {
const [todo, dispatch] = useReducer(reducer, mockTodo);
const idRef = useRef(3);
const onCreate = (content) => {
dispatch({
type: "CREATE",
newItem: {
id: idRef.current,
content,
isDone: false,
createDate: new Date().getTime(),
},
})
idRef.current += 1;
};
const onUpdate = (targetId) => {
dispatch({
type: "UPDATE",
targetId,
});
};
const onDelete = (targetId) => {
dispatch({
type: "DELETE",
targetId,
});
};
return (
<div className="App">
<Header />
<TodoEditor onCreate={onCreate} />
<TodoList todo={todo} onUpdate={onUpdate} onDelete={onDelete} />
</div>
);
}
export default App;



출처 : 이정환, 『한 입 크기로 잘라먹는 리액트』, 프로그래밍인사이트(2023).
'DEVELOPMENT > react' 카테고리의 다른 글
| 13. 컴포넌트 트리에 데이터 공급하기 (0) | 2025.01.08 |
|---|---|
| 12. 최적화 (0) | 2025.01.06 |
| 10. 할일 관리 앱 만들기 (0) | 2024.12.30 |
| 9. 리액트를 다루는 기술 - hooks (0) | 2024.12.23 |
| 8. 라이프 사이클과 리액트 개발자 도구 (0) | 2024.12.23 |