React에는 여러가지 상태관리하는 방법들과 라이브러리들이 있다. 대표적으로 useState를 가장 많이 사용할 것이다. 또 라이브러리에는 Redux가 존재한다. 이번에 알아볼 것은 React가 이제 업데이트를 하면서 제공하는 useReducer이다.
useState 같은 경우는 기본적인 React의 상태관리이다. 하지만 코드가 지저분해지는 경우가 종종 있을 뿐만 아니라 이 코드를 재사용하기도 어렵다. 그래서 나온 것이 useReducer이다. useReducer 같은 경우에는 코드의 재사용이 가능하다.
어떻게 가능한지 살펴보자.
일단 이렇게 reducer라는 폴더를 따로 만든 다음에 useReducer와 연결할 js 파일을 하나 만들어 준다.
그리고 그 JS파일에 이제 상태를 변경할 것들을 코드로 작성해 주면 되는데
export default function foodReducer(food, action) {
switch (action.type) {
case 'updated': {
const {prev, current} = action;
return {
...food,
chefs: food.chefs.map(chef => {
if (chef.name === prev) {
return {...chef, name: current};
}
return chef;
}),
};
}
case 'added': {
const {name, title} = action;
return {
...food,
chefs: [...food.chefs, {name, title}],
};
}
case 'deleted': {
return {
...food,
chefs: food.chefs.filter(chef => chef.name != action.name),
};
}
default: {
throw Error(`알 수 없는 액션 타입이다.`);
}
}
}
이 foodReducer라는 함수는 파라미터를 두 개를 받는다. 하나는 food고 다른 하나는 action이다. food는 이제 우리가 연결할 컴포넌트에 있는 상태관리하는 변수가 되겠고 action은 useReducer에서 dispatch라는 함수를 지원하는데 거기에 입력하는 객체 혹은 값이라고 할 수 있다.
그래서 이 switch문을 통해서 내가 업데이트를 하고 싶으면 action에서 받아오는 type에 따라 상태관리에 관한 코드들을 입력해주면 된다.
import React, {useReducer} from 'react';
import foodReducer from './reducer/food_reducer';
export default function AppFoodReducer() {
const [food, dispatch] = useReducer(foodReducer, initialFood);
const handleUpdate = () => {
const prev = prompt(`어떤 쉐프의 이름을 바꾸고 싶은가요?`);
const current = prompt(`쉐프의 이름을 무엇으로 바꾸고 싶은가요?`);
dispatch({type: 'updated', prev, current});
};
const handleAdd = () => {
const name = prompt(`쉐프의 이름을 입력해주세요`);
const title = prompt(`쉐프의 타이틀을 입력해주세요`);
dispatch({type: 'added', name, title});
};
const handleDelete = () => {
const name = prompt(`누구의 이름을 삭제하고 싶은가요?`);
dispatch({type: 'deleted', name});
};
return (
<div>
<h1>
Best Pasta의 {food.name}는 별점 {food.rating}
</h1>
<p>{food.name}의 가게의 주방장은 : </p>
<ul>
{food.chefs.map((chef, index) => (
<li key={index}>
{' '}
{chef.name} ({chef.title})
</li>
))}
</ul>
<button onClick={handleUpdate}>주방장 이름 바꾸기</button>
<button onClick={handleAdd}>주방장 추가하기</button>
<button onClick={handleDelete}>주방장 삭제</button>
</div>
);
}
const initialFood = {
name: '스파게티',
rating: '★★★★★',
chefs: [
{name: 'jay', title: 'leader chef'},
{name: 'bread', title: '견습생 쉐프'},
],
};
food_reducer에 연결한 AppFoodReducer를 살펴보면 useReducer에 우리가 만든 food_reducer 함수를 전달하고 최초의 상태관리 값도 같이 전달하면 된다. 이후에 food라는 변수와 dispatch 함수를 지원하는데 dispatch 함수를 통해서 원하는 type과 값들을 객체로 전달해주면 dispatch가 food_reducer에 action이라는 파라미터로 넘겨준다.
내가 이걸 공부하면서 느낀건 바로 useReducer로 적용해서 상태관리를 하는 것은 매우 힘들다고 생각이 든다. 일단은 먼저 useState를 통해서 상태관리를 하는데 너무 코드가 지저분해지거나 좀 반복적인 코드가 보인다? 혹은 이걸 다른 컴포넌트에도 재사용할 수 있겠는데 라고 느낀다면 그때 useReducer를 사용하는 것이 좋다고 생각한다.
'React' 카테고리의 다른 글
Redux에 대해서 (0) | 2024.06.15 |
---|---|
ContextAPI 이용해서 다크모드 사용하기(React) (2) | 2024.01.07 |
Component 재사용하기 (React) (0) | 2023.12.31 |
React 상태관리 - UseImmer (0) | 2023.12.27 |
마우스 따라가는 원형 만들기(React) (0) | 2023.12.24 |