[React] 27. useReducer로 투두리스트 업데이트

서회정's avatar
Mar 06, 2026
[React] 27. useReducer로 투두리스트 업데이트

 
useReducer로 기존에 만들었던 투두리스트 앱의
상태 관리 훅을 useState가 아닌, useReducer로 변경하여
상태 관리를 해보자.
 

1. useReducer로 상태관리 훅 사용

 
먼저 기존의 state를 삭제하고 useReducer를 활용한 state를 만들자.
첫 번째 인수로 실질적으로 상태를 변경하는 함수 ruducer를 넣고
초기값으로 mockData를 넣어주자.
 
const [todos, dispatch] = useReducer(reducer, mockData);
 
다음으로는 reducer 함수를 만들어보자.
첫 번째 인수로 현재 상태를 의미하는 state
두 번째 인수로는 요청 형태를 담는 action 객체를 넣어주자.
 
function reducer(state, action) {}
 

2. onCreate 함수 수정

 
기존에 만들어두었던 onCreate 함수 내용을 삭제하고
dispatch를 호출하는 코드를 넣어주자.
 
const onCreate = (content) => { dispatch(); };
 
이 액션 객체에는 type 프로퍼티로 CREATE
date 프로퍼티로 추가될 객체의 값을 넣어주자.
 
const onCreate = (content) => { dispatch({ type: "CREATE", data: { id: idRef.current++, isComplete: false, content: content, date: new Date().getTime(), }, }); };
 
다음으로 reducer 함수에서 switch문을 작성해서
action.typeCREATE일 때 기존 상태를 스프레드 연산자로 뿌리고
그 앞에 action.data에서 적어두었던 정보를 끼워넣을 수 있게 같이 적어주자.
 
function reducer(state, action) { switch (action.type) { case "CREATE": return [action.data, ...state]; } }
 
추가 잘됨!
 
notion image
 

3. onUpdate 함수 수정

 
다음으로는 수정하는 로직을 수정하자.
 
마찬가지로 기존에 함수 내부에 있던 코드를 삭제하고
dispatch 함수를 호출해주자.
 
const onUpdate = (targetId) => { dispatch(); };
 
인수로는 UPDATE라는 typetargetId 프로퍼티를 가진
액션 객체를 넣어주자.
 
const onUpdate = (targetId) => { dispatch({ type: "UPDATE", targetId: targetId, }); };
 
reducer함수로 가서 UPDATE라는 case를 추가해준 뒤
현재 statemap메서드를 호출하여 인수로 item을 받자.
 
item을 순회하면서 idtargetId와 같은 요소를 찾아
요소 안의 내용을 스프레드 연산자로 뿌린 후 그 중에서도
isComplete만 토글로 변경될 수 있게 변경해주자.
 
idtargetId와 일치하지 않을 때는 item을 그대로 넣어주자.
삼항연산자로 보다 깔끔하게 작성했다.
 
function reducer(state, action) { switch (action.type) { case "CREATE": return [action.data, ...state]; case "UPDATE": return state.map((item) => item.id === action.targetId ? { ...item, isComplete: !item.isComplete } : item, ); } }
 
아주 잘되시긔
 
notion image

4. onDelete 함수 수정

 
마지막으로 삭제 로직도 수정해보자.
 
마찬가지로 onDelete함수 내에 기존 코드를 제거하고
dispatch함수를 호출하여 typetargetId를 가진
액션 객체를 인수로 넣어주자.
 
const onDelete = (targetId) => { dispatch({ type: "DELETE", targetId: targetId, }); };
 
reducer함수에서 DELETE case를 추가하고
filter메서드를 사용하여 idtargetId가 일치하지 않는 요소만
필터링하여 반환하면 삭제를 클릭한 요소는 삭제된다.
 
마지막엔 default로 현재 상태인 state를 돌려주자.
(작성된 case가 아닌 경우에 다른 로직이 실행되는 것 방지)
 
function reducer(state, action) { switch (action.type) { case "CREATE": return [action.data, ...state]; case "UPDATE": return state.map((item) => item.id === action.targetId ? { ...item, isComplete: !item.isComplete } : item, ); case "DELETE": return state.filter((item) => item.id !== action.targetId); default: state; } }
 
만들었던 노션 정리하기 라는 content를 가진 요소가 제거되었다!
 
notion image
Share article

clubnerdy