
# useReducer
- useState 처럼 리액트의 상태관리를 돕는 도구
- 복잡한 상태변화 로직을 컴포넌트에서 분리
- 복잡한 코드를 깔끔하게 정리할 수 있어서 유지보수에 좋음
- Readucer / Dispatch / Action 으로 이루어져 있다.
예를들어 우리가 은행거래를 할 때를 생각하면 쉽다.

1. 철수가 은행에서 거래를 하기위해 요구(Dispatch)를 한다.
2. 그 요구에는 '만원을 출금해주세요' 라는 내용(action)이 있다.
3. 그리고나서 은행(Reducer)에 전달을 한다.
4. 은행은 내용대로 처리를 한뒤 철수의 은행거래내역(state)에 업데이트를 해준다.
- reducer : state를 업데이트 하는 역할(은행)
- dispatch : state 업데이트를 위한 요구
- action : 요구의 내용
# 예제 1
import React, { useReducer, useState } from 'react';
const ACTION_TYPES = {
deposit: 'deposit',
withdraw: 'withdraw',
}
const reducer = (state, action) => {
switch (action.type){
case ACTION_TYPES.deposit :
return state + action.payload;
case ACTION_TYPES.withdraw :
return state - action.payload;
default:
return state;
}
};
function App() {
const [number, setNumber] = useState(0);
const [money, dispatch] = useReducer(reducer, 0);
return (
<div>
<h2>useReducer 은행에 오신것을 환영합니다.</h2>
<p>잔고: {money}원</p>
<input
type='number'
value={number}
onChange={(e) => setNumber(parseInt(e.target.value))}
step='1000'
/>
<button onClick={() => {
dispatch({type: ACTION_TYPES.deposit, payload: number});
}}>예금</button>
<button onClick={() => {
dispatch({type: ACTION_TYPES.withdraw, payload: number});
}}>출금</button>
</div>
);
}
export default App;
- dispatch에 action을 전달할 때 그안에는 보통 {} 객체 형태로 전달하고 type을 적어준다.
- type 안에는 요구를 적어준다.
- reducer가 리턴하는 값이 새로 업데이트되는 값이다.
- 보통 reducer 안에는 if..else문, switch..case문을 사용한다.
- reducer의 장점은 전달받은 action 대로만 state를 업데이트 시켜준다.
# 예제 2
import React, { useReducer, useState } from 'react';
import Student from './Student';
const reducer = (state, action) => {
switch(action.type){
case 'add-student':
const name = action.payload.name;
const newStudent = {
id: Date.now(),
name,
isHere: false,
}
return {
count: state.count + 1,
students: [...state.students, newStudent],
}
case 'delete-student':
return {
count: state.count - 1,
students: state.students.filter(student => student.id !== action.payload.id),
}
case 'mark-student':
return {
count: state.count,
students: state.students.map(student => {
if(student.id === action.payload.id){
return {...student, isHere: !student.isHere}
}
return student;
})}
default:
return state;
}
}
const initialState = {
count : 0,
students: [],
}
function App() {
const [name, setName] = useState('');
const [studentInfo, dispatch] = useReducer(reducer, initialState)
return (
<div>
<h1>출석부</h1>
<p>총 학생 수: {studentInfo.count}</p>
<input
type="text"
placeholder='이름을 입력해주세요'
value={name}
onChange={(e) => setName(e.target.value)}
/>
<button onClick={() => {
dispatch({type: 'add-student', payload: {name}})
}}>추가</button>
{studentInfo.students.map((student) => {
return (
<Student
key={student.id}
name={student.name}
dispatch={dispatch}
id={student.id}
isHere={student.isHere}
/>
);
})}
</div>
);
}
export default App;
import React from 'react';
const Student = ({name, dispatch, id, isHere}) => {
return(
<div>
<span
style={{
textDecoration: isHere ? 'line-through' : 'none',
color: isHere ? 'gray' : 'black',
}}
onClick={() => {
dispatch({type: 'mark-student', payload: {id}})
}}
>{name}</span>
<button onClick={() => {
dispatch({type: 'delete-student', payload: {id}})
}}>삭제</button>
</div>
)
}
export default Student;
📌 참고
별코딩 | 리액트 훅스 시리즈
'Front-end > React' 카테고리의 다른 글
리액트에서 checkbox 오류 해결하기 (0) | 2023.12.28 |
---|---|
[React] CSR (클라이언트 사이드 렌더링) 과 SSR (서버 사이드 렌더링) (0) | 2023.03.07 |
[React] 컴포넌트 최적화 - React.memo (0) | 2023.02.28 |
[React] React Hooks : useCallback (0) | 2023.02.27 |
[React] React Hooks : useMemo (0) | 2023.02.24 |

# useReducer
- useState 처럼 리액트의 상태관리를 돕는 도구
- 복잡한 상태변화 로직을 컴포넌트에서 분리
- 복잡한 코드를 깔끔하게 정리할 수 있어서 유지보수에 좋음
- Readucer / Dispatch / Action 으로 이루어져 있다.
예를들어 우리가 은행거래를 할 때를 생각하면 쉽다.

1. 철수가 은행에서 거래를 하기위해 요구(Dispatch)를 한다.
2. 그 요구에는 '만원을 출금해주세요' 라는 내용(action)이 있다.
3. 그리고나서 은행(Reducer)에 전달을 한다.
4. 은행은 내용대로 처리를 한뒤 철수의 은행거래내역(state)에 업데이트를 해준다.
- reducer : state를 업데이트 하는 역할(은행)
- dispatch : state 업데이트를 위한 요구
- action : 요구의 내용
# 예제 1
import React, { useReducer, useState } from 'react';
const ACTION_TYPES = {
deposit: 'deposit',
withdraw: 'withdraw',
}
const reducer = (state, action) => {
switch (action.type){
case ACTION_TYPES.deposit :
return state + action.payload;
case ACTION_TYPES.withdraw :
return state - action.payload;
default:
return state;
}
};
function App() {
const [number, setNumber] = useState(0);
const [money, dispatch] = useReducer(reducer, 0);
return (
<div>
<h2>useReducer 은행에 오신것을 환영합니다.</h2>
<p>잔고: {money}원</p>
<input
type='number'
value={number}
onChange={(e) => setNumber(parseInt(e.target.value))}
step='1000'
/>
<button onClick={() => {
dispatch({type: ACTION_TYPES.deposit, payload: number});
}}>예금</button>
<button onClick={() => {
dispatch({type: ACTION_TYPES.withdraw, payload: number});
}}>출금</button>
</div>
);
}
export default App;
- dispatch에 action을 전달할 때 그안에는 보통 {} 객체 형태로 전달하고 type을 적어준다.
- type 안에는 요구를 적어준다.
- reducer가 리턴하는 값이 새로 업데이트되는 값이다.
- 보통 reducer 안에는 if..else문, switch..case문을 사용한다.
- reducer의 장점은 전달받은 action 대로만 state를 업데이트 시켜준다.
# 예제 2
import React, { useReducer, useState } from 'react';
import Student from './Student';
const reducer = (state, action) => {
switch(action.type){
case 'add-student':
const name = action.payload.name;
const newStudent = {
id: Date.now(),
name,
isHere: false,
}
return {
count: state.count + 1,
students: [...state.students, newStudent],
}
case 'delete-student':
return {
count: state.count - 1,
students: state.students.filter(student => student.id !== action.payload.id),
}
case 'mark-student':
return {
count: state.count,
students: state.students.map(student => {
if(student.id === action.payload.id){
return {...student, isHere: !student.isHere}
}
return student;
})}
default:
return state;
}
}
const initialState = {
count : 0,
students: [],
}
function App() {
const [name, setName] = useState('');
const [studentInfo, dispatch] = useReducer(reducer, initialState)
return (
<div>
<h1>출석부</h1>
<p>총 학생 수: {studentInfo.count}</p>
<input
type="text"
placeholder='이름을 입력해주세요'
value={name}
onChange={(e) => setName(e.target.value)}
/>
<button onClick={() => {
dispatch({type: 'add-student', payload: {name}})
}}>추가</button>
{studentInfo.students.map((student) => {
return (
<Student
key={student.id}
name={student.name}
dispatch={dispatch}
id={student.id}
isHere={student.isHere}
/>
);
})}
</div>
);
}
export default App;
import React from 'react';
const Student = ({name, dispatch, id, isHere}) => {
return(
<div>
<span
style={{
textDecoration: isHere ? 'line-through' : 'none',
color: isHere ? 'gray' : 'black',
}}
onClick={() => {
dispatch({type: 'mark-student', payload: {id}})
}}
>{name}</span>
<button onClick={() => {
dispatch({type: 'delete-student', payload: {id}})
}}>삭제</button>
</div>
)
}
export default Student;
📌 참고
별코딩 | 리액트 훅스 시리즈
'Front-end > React' 카테고리의 다른 글
리액트에서 checkbox 오류 해결하기 (0) | 2023.12.28 |
---|---|
[React] CSR (클라이언트 사이드 렌더링) 과 SSR (서버 사이드 렌더링) (0) | 2023.03.07 |
[React] 컴포넌트 최적화 - React.memo (0) | 2023.02.28 |
[React] React Hooks : useCallback (0) | 2023.02.27 |
[React] React Hooks : useMemo (0) | 2023.02.24 |