useReducer
useReducer란?
useReducer훅은 useState 훅과 동일하게 컴포넌트 내부에 새로운 state를 생성하는 메서드다.
모든 useState는 useReducer로 대체 가능하지만 useReducer는 useState와 달리 상태를 관리하는 코드를 컴포넌트 외부로 분리할 수 있다는 차이점이 있다.
useReducer 사용법
import { useReducer } from 'react';
function reducer(state, action) {
...
}
function App() {
const [state, dispatch] = useReducer(reducer, initialArg);
return(
...
)
}
useReducer 호출하면 현재 state와 상태 변화를 요청하는 dispatch 함수를 반환한다.
컴포넌트 바깥에서 reducer 함수를 생성하고 state와 action을 reducer 함수에 전달한다.
상태를 변경하고 싶으면 dispatch 함수에 인수로 상태를 어떻게 변화시킬지 객체로 작성하면 된다. 이때 해당 객체는 action 객체라고 부른다.
dispatch 함수를 호출하면 useReducer가 해당 요청을 처리해주기 위해서 상태를 변화시키는 reducer 함수를 호출한다.
보통 reducer 함수 안에서 switch 문을 사용해 액션 타입 별로 동작할 로직을 작성한다.
useState 훅을 useReducer 훅으로 마이그레이션
useState 훅 사용
import { useState, useRef } from "react";
import Editor from "./components/Editor";
import List from "./components/List";
const mockData = [
{
id: 0,
isDone: false,
content: "React 공부하기",
date: new Date().getTime(),
},
{
id: 1,
isDone: false,
content: "빨래하기",
date: new Date().getTime(),
},
{
id: 2,
isDone: false,
content: "노래 연습하기",
date: new Date().getTime(),
},
];
function App() {
const [todos, setTodos] = useState(mockData);
const idRef = useRef(3);
const onCreate = (content) => {
const newTodo = {
id: idRef.current++,
isDone: false,
content: content,
date: new Date().getTime(),
};
setTodos([newTodo, ...todos]);
};
const onUpdate = (targetId) => {
setTodos(
todos.map((todo) =>
todo.id === targetId ? { ...todo, isDone: !todo.isDone } : todo
)
);
};
const onDelete = (targetId) => {
setTodos(todos.filter((todo) => todo.id !== targetId));
};
return (
<div>
<Editor onCreate={onCreate} />
<List todos={todos} onUpdate={onUpdate} onDelete={onDelete} />
</div>
);
}
export default App;
useReducer 훅 사용
import { useReducer, useRef } from "react";
import Editor from "./components/Editor";
import List from "./components/List";
const mockData = [
{
id: 0,
isDone: false,
content: "React 공부하기",
date: new Date().getTime(),
},
{
id: 1,
isDone: false,
content: "빨래하기",
date: new Date().getTime(),
},
{
id: 2,
isDone: false,
content: "노래 연습하기",
date: new Date().getTime(),
},
];
function reducer(state, action) {
switch (action.type) {
case "CREATE":
return [action.data, ...state];
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 [todos, dispatch] = useReducer(reducer, mockData);
const idRef = useRef(3);
const onCreate = (content) => {
dispatch({
type: "CREATE",
data: {
id: idRef.current++,
isDone: false,
content: content,
date: new Date().getTime(),
},
});
};
const onUpdate = (targetId) => {
dispatch({
type: "UPDATE",
targetId: targetId,
});
};
const onDelete = (targetId) => {
dispatch({
type: "DELETE",
targetId: targetId,
});
};
return (
<div>
<Editor onCreate={onCreate} />
<List todos={todos} onUpdate={onUpdate} onDelete={onDelete} />
</div>
);
}
export default App;
'기록 > TIL' 카테고리의 다른 글
[TIL] Context (0) | 2024.11.15 |
---|---|
[TIL] useMemo / React.memo / useCallback (1) | 2024.11.14 |
[TIL] 생명주기 / useEffect (1) | 2024.11.12 |
[TIL] State 끌어올리기 / useRef (0) | 2024.11.11 |
[TIL] React Hooks / useState / Custom Hook (0) | 2024.11.10 |