[React] 26. useReducer

서회정's avatar
Mar 06, 2026
[React] 26. useReducer

 

1. useReducer란

 
💡
컴포넌트 내부에 새로운 State를 생성하는 리액트 훅
모든 useStateuseReducer로 대체 가능
 
notion image
 

2. useState와 useReducer의 차이

 
💡
useReducer는 상태 관리 코드를 컴포넌트 외부로 분리할 수 있다
 
notion image
 
useReducer를 사용할 때는 컴포넌트 내부에서는
새로운 스테이트를 생성만 하고,
외부에서 reducer라는 이름으로 상태 관리 코드를 작성하여
사용할 수 있다.
 
notion image
 

3. useReducer 사용하는 이유

 
💡
상태를 외부에서 관리할 수 있는 useReducer라는 훅은 왜 필요할까?
 
리액트의 컴포넌트의 주된 역할은 UI를 렌더링 하는 것이다.
따라서 상태관리 코드가 길고 복잡해지는 경우에는 유지보수 측면에서 좋지 않다.
 
그래서 이를 따로 분리하여 상태관리를 할 수 있도록 도와주는 useReducer를 사용하는 것이다.
 
앞서 만들어본 투두리스트 앱에서도 상태관리 코드가 너무 길다!
 
notion image
 

4. 카운터 예제로 활용

 
간단한 카운트 기능이 있는 예제로 사용 방법을 살펴보자
 
먼저 예제가 될 Exam컴포넌트를 만들어주자.
+버튼과 -버튼이 있는 형태가 될 것이다.
 
import { useReducer } from "react"; const Exam = () => { return ( <div> <h1>0</h1> <button>+</button> <button>-</button> </div> ); }; export default Exam;
 
useReducer를 사용하기 위해 훅을 불러오고
새로운 스테이트를 만들어주자.
 
여기서 기존에 state에서 상태변화함수가 들어갔던 자리에 있는
dispatch는 발송하다, 급송하다 라는 뜻을 가지고 있으며
여기서는 단순히 상태 변화가 있어야 한다고 알리는, 발송하는 함수이다.
 
import { useReducer } from "react"; const Exam = () => { const [state, dispatch] = useReducer(); return ( <div> <h1>0</h1> <button>+</button> <button>-</button> </div> ); }; export default Exam;
 
컴포넌트에서 상태 변화가 일어나야 한다고 dispatch 함수를 호출하면
상태 변화가 요청이 되어 useReducer가 실제로 상태 변화를 일으키는
함수를 호출하게 되는데, 이는 직접 만들어야 한다.
 
이렇게 만든 reducer라는 함수는 useReducer의 첫 번째 인자로 넣어준다.
그리고 useReducer의 두 번째 인자로는 초기 값을 넣자.
여기까지 했으면 h1의 상수를 state로 넣었을 때 화면에 출력이 된다.
 
import { useReducer } from "react"; function reducer() {}; const Exam = () => { const [state, dispatch] = useReducer(reducer, 0); return ( <div> <h1>{state}</h1> <button>+</button> <button>-</button> </div> ); }; export default Exam;
 
다음으로 실제로 버튼을 눌렀을 때 dispatch를 호출하여
상태 변화를 일으킬 로직을 작성해 주어야 한다.
 
먼저 플러스 버튼부터 만들어보자.
이벤트 핸들러를 만들고 내부에 dispatch함수를 호출하여
인자로 상태가 어떻게 변경될 것인지 객체 형태로 전달한다.
 
이 객체에서는 typedata라는 프로퍼티가 들어가게 된다.
우리는 1씩 증가시키는 식을 만들고자 하기 때문에
typeINCREASE, data1로 넣어주자.
 
참고로 요청 형태를 담고 있는 이 객체는 액션 객체라고 부른다.
 
import { useReducer } from "react"; function reducer() {}; const Exam = () => { const [state, dispatch] = useReducer(reducer, 0); const onClickPlus = () => { dispatch({ type: "INCREASE", // 요청 타입 data: 1, }) } return ( <div> <h1>{state}</h1> <button onClick={onClickPlus}>+</button> <button>-</button> </div> ); }; export default Exam;
 
onClickPlus이벤트 핸들러가 실행될 때,
dispatch 함수가 호출되며 useReducer가 실제로
상태를 변경하기 위해 변경을 실질적으로 처리하는
reducer라는 함수를 호출하게 된다.
 
ruducer함수의 매개변수로는 먼저 현재 상태인 state를 제공하고
두 번째로는 요청의 내용이 담긴 action객체를 제공한다.
 
import { useReducer } from "react"; function reducer(state, action) { console.log(state, action); }; const Exam = () => { const [state, dispatch] = useReducer(reducer, 0); const onClickPlus = () => { dispatch({ type: "INCREASE", // 요청 타입 data: 1, }) } return ( <div> <h1>{state}</h1> <button onClick={onClickPlus}>+</button> <button>-</button> </div> ); }; export default Exam;
 
해당 함수 내에 stateaction을 콘솔에 출력하는 코드를 입력하면
출력된 결과를 확인할 수 있다.
 
notion image
 
콘솔 출력 코드를 삭제하고 그 자리에 조건문으로
actiontypeINCREASE일 때 actiondata를 현재 state에 더하여
반환하는 코드를 작성해주면 플러스버튼의 로직 완성이다.
 
if (action.type === "INCREASE") { return state + action.data; }
 
마찬가지로 마이너스 버튼도 동일하게 만들어주자.
 
import { useReducer } from "react"; function reducer(state, action) { if (action.type === "INCREASE") { return state + action.data; } else if (action.type === "DECREASE") { return state - action.data; } } const Exam = () => { const [state, dispatch] = useReducer(reducer, 0); const onClickPlus = () => { dispatch({ type: "INCREASE", data: 1, }); }; const onClickMinus = () => { dispatch({ type: "INCREASE", data: 1, }); }; return ( <div> <h1>{state}</h1> <button onClick={onClickPlus}>+</button> <button onClick={onClickMinus}>-</button> </div> ); }; export default Exam;
 
만일 reducer 안에 액션들이 많아지는 경우엔 if문보다는
switch문을 사용하는 것이 일반적이다.
 
import { useReducer } from "react"; function reducer(state, action) { switch (action.type) { case "INCREASE": return state + action.data; case "DECREASE": return state - action.data; } } const Exam = () => { const [state, dispatch] = useReducer(reducer, 0); const onClickPlus = () => { dispatch({ type: "INCREASE", data: 1, }); }; const onClickMinus = () => { dispatch({ type: "INCREASE", data: 1, }); }; return ( <div> <h1>{state}</h1> <button onClick={onClickPlus}>+</button> <button onClick={onClickMinus}>-</button> </div> ); }; export default Exam;
 

전체메모

import { useReducer } from "react"; // reducer : 변환기 // -> 상태를 실제로 변화시키는 변환기 역할 // 첫 번째 인수 : 현재 상태 // 두 번째 인수 : 액션 객체 function reducer(state, action) { console.log(state, action); switch (action.type) { case "INCREASE": return state + action.data; case "DECREASE": return state - action.data; default: return state; } // if (action.type === "INCREASE") { // return state + action.data; // } else if (action.type === "DECREASE") { // return state - action.data; // } } const Exam = () => { // 첫 번째 인수 // dispatch : 발송하다, 급송하다 // -> 상태 변화가 있어야한다고 알리는, 발송하는 함수 // 두 번째 인수 // 상태의 초기값 const [state, dispatch] = useReducer(reducer, 0); const onClickPlus = () => { // 인수 : 상태가 어떻게 변화되길 원하는지 // 객체 형태 -> 액션 객체 dispatch({ type: "INCREASE", // 요청 타입 data: 1, }); }; const onClickMinus = () => { dispatch({ type: "DECREASE", data: 1, }); }; return ( <div> <h1>{state}</h1> <button onClick={onClickPlus}>+</button> <button onClick={onClickMinus}>-</button> </div> ); }; export default Exam;
 
Share article

clubnerdy