useReducer
- 컴포넌트 내부에 새로운 State를 생성하는 React Hook
- 모든 useState는 useReducer로 대체 가능
- useState는 state를 관리하는 코드를 컴포넌트 내부에만 작성 가능
- 하지만, useReducer를 사용하면 state를 관리하는 코드를 컴포넌트 외부에 작성할 수 있어 코드의 가독성을 높일 수 있다
사용하기
import { act, useReducer } from 'react';
const 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: 'DECREASE',
data: 1,
});
};
return (
<div>
<h1>{state}</h1>
<button onClick={onClickPlus}>+</button>
<button onClick={onClickMinus}>-</button>
</div>
);
};
export default Exam;
1. useReducer 선언
const Exam = () => {
const [state, dispatch] = useReducer(reducer, 0);
- state의 이름은 todo 등 원하는 것으로 해도 됨
- 뒤에는 reducer 함수와 기본값을 받음(기본값 생략 가능)
- reducer는 컴포넌트 외부에 따로 선언해줌(아래에서 자세히)
- useReducer는 아래와 같이 import 해서 가져와야 함
import { useReducer } from 'react';
2. dispatch 함수 생성
const onClickPlus = () => {
dispatch({
type: 'INCREASE',
data: 1,
});
};
const onClickMinus = () => {
dispatch({
type: 'DECREASE',
data: 1,
});
};
- 그 뒤 함수에 dispatch 를 이용해 type과 data의 값을 넘겨줌
- data의 값이 여러개일 경우 객체({ }) 형태로 전달
3. 이벤트 핸들러 부착
return (
<div>
<h1>{state}</h1>
<button onClick={onClickPlus}>+</button>
<button onClick={onClickMinus}>-</button>
</div>
);
- onClick 이벤트 핸들러에 생성한 함수 부착
4. reducer 설정
const reducer = (state, action) => {
if (action.type === 'INCREASE') {
return state + action.data;
} else if (action.type === 'DECREASE') {
return state - action.data;
}
};
- 컴포넌트 외부에 reducer 함수 생성
- state와 action 을 값으로 받음
- state는 현상태인거고, action은 수정된 값(setState 느낌)
- if와 else if를 이용해 type에 맞게 동작을 정해줌
- return을 사용해서 넘겨줌!
const reducer = (state, action) => {
switch (action.type) {
case 'INCREASE':
return state + action.data;
case 'DECREASE':
return state - action.data;
default:
return state;
}
};
- 조건이 많을 경우 if문보다 switch와 case를 더 많이 사용함
- type별로 작성하고 default를 이용해 기본값을 넘겨줌
TodoList App 을 useReducer로 수정하기
1. onCreate
import { useState, useRef, useReducer } from 'react';
import './App.css';
import Editor from './components/Editor';
import Header from './components/Header';
import List from './components/List';
import Exam from './components/Exam';
const mockTodo = [...];
function reducer(state, action) {
switch (action.type) {
case 'CREATE':
return [action.data, ...state];
default:
return state;
}
}
function App() {
const [state, dispatch] = useReducer(reducer, mockTodo);
const idRef = useRef(3);
const onCreate = (content) => {
dispatch({
type: 'CREATE',
data: {
id: idRef.current++,
content: content,
isDone: false,
createdDate: new Date().getTime(),
},
});
};
return (
<div className="App">
<Header />
<Editor onCreate={onCreate} />
<List todo={state} onUpdate={onUpdate} onDelete={onDelete} />
</div>
);
}
export default App;
- 기존에 넘겨주던 값을 onCreate에 dispatch를 붙여 data에 담아서 보내줌
- dispatch({}) 괄호 주의하기! 여러개니까 객체로 줘야함
2. onUpdate, onDelete
import { useState, useRef, useReducer } from 'react';
(...)
const mockTodo = [...];
function reducer(state, action) {
switch (action.type) {
case 'UPDATE':
return state.map((item) =>
item.id === action.targetId ? { ...item, isDone: !item.isDone } : item,
);
case 'DELETE':
return state.filter((item) => item.id !== action.targetId);
default:
return state;
}
}
function App() {
const [state, dispatch] = useReducer(reducer, mockTodo);
const idRef = useRef(3);
const onUpdate = (targetId) => {
dispatch({
type: 'UPDATE',
targetId: targetId,
});
};
const onDelete = (targetId) => {
dispatch({
type: 'DELETE',
targetId: targetId,
});
};
return (
<div className="App">
<Header />
<Editor onCreate={onCreate} />
<List todo={state} onUpdate={onUpdate} onDelete={onDelete} />
</div>
);
}
export default App;
- Update와 Delete에는 targetId만 필요하므로 그 값만 넘겨줌
- 자세한 state 관리는 컴포넌트 외부의 reducer에서 처리함
- 매개변수로 전달된 값은 action에 들어있음
'개발새발개발 > React' 카테고리의 다른 글
[React] 최적화하기 (Optimization) - useMemo, memo, useCallback (0) | 2025.02.19 |
---|---|
[React] Context 사용해서 props 없이 편하게 데이터 전달하기 (0) | 2025.02.18 |
[React + TypeScript + Tailwind] 가독성 높이는 UI 컴포넌트 만들기 (1) | 2025.02.14 |
[React] VSCode Prettier 적용 안됨 5가지 해결 방법 (2) | 2025.02.13 |
[React+Typescript] Todos 앱 만들기 (0) | 2025.02.11 |
댓글