Use-immer를 사용하는 이유는 복잡한 객체를 복사할 때, 스프레드 연산자를 많이 사용하면 코드가 복잡해지기 때문입니다. Use-immer를 활용하면 복잡한 객체를 좀 더 수월하게 복사하고 관리할 수 있습니다.
기본 스테이트 객체 복사 너무 복잡함 ...스프레드 오퍼레이터를 사용해야한다는 단점이 있습니다.
import React from "react";
function App() {
const state = {
name: "Lee",
age: 20,
address: {
country: "Korea",
city: "Seoul",
},
whatHave: {
home: {
price: 1_000_000,
address: {
city: "Seoul",
detail: "Gangnam 23",
},
},
money: 1_000_000,
},
};
// const newState = { ...state };
const newState = {
...state,
address: { ...state.address },
whatHave: { ...state.whatHave, home: { ...state.whatHave.home } },
};
console.log(`🚨`, newState === state);
console.log(`🙋`, newState.address === state.address);
console.log(`⛔️`, newState.whatHave === state.whatHave);
console.log(`💕`, newState.whatHave.home === state.whatHave.home);
return (
<>
<b> {state.name} </b>
</>
);
}
export default App;
Use-immer를 사용하면 useState처럼 사용할수 있고 복잡한 객체들을 상태관리를 수월하게 할 수 있습니다.
import React from "react";
import { useImmer } from "use-immer";
function App() {
const state = {
name: "Lee",
age: 20,
address: {
country: "Korea",
city: "Seoul",
},
whatHave: {
home: {
price: 1_000_000,
address: {
city: "Seoul",
detail: "Gangnam 23",
},
},
money: 1_000_000,
},
};
const [house, setHouse] = useImmer(state);
const twoTimes = () => {
setHouse((draft) => {
draft.whatHave.home.price *= 2;
});
};
const handleKeyPress = (e) => {
setHouse((draft) => {
draft.name = e.target.value;
});
};
return (
<div>
<h2>{house.whatHave.home.price}</h2>
<button onClick={twoTimes}> prices 2 times</button>
{<h2>{house.name}</h2>}
<input
type="text"
defaultValue={house.name}
onKeyPress={handleKeyPress}
/>
</div>
);
}
export default App;
관리하는 state를 useState로 관리하면 10개-20개 이상 생기면 관리하기가 매우 힘듭니다.
변화할때마다 재 렌더링 한다 생각하면 너무 끔찍합니다.
그래서 useReducer를 사용합니다.
useReducer는 컴포넌트 안에서 관리하기 보단 새로운 함수를 만들어서 관리를 합니다.
쉽게 말해 reducer에서 state 관리를 따로 빼서 활용한다고 생각하시면 됩니다.
import React from "react";
import { useReducer } from "react";
import { Button } from "@mui/material";
function reducer(state, action) {//인자값으로 스테이트값 action은 객체
switch (action.type) {
case `INCREMENT`:
return { value: state.value + 1 };
case `DECREMENT`:
return { value: state.value - 1 };
default:
return state;
}
}
const Counter = () => {
const [state, dispatch] = useReducer(reducer, { value: 10 });// 인자값엔는 함수와 초기값이 들어갑니다.
//num은 state값, dispatch는 재렌더링 시키기위한 함수
return (
<>
<h3 style={{ backgroundColor: `aqua` }}>
Current Counter Value is <b style={{ color: "blue" }}>{state.value}</b>
</h3>
<Button
variant="contained"
and
color="info"
onClick={() => {
dispatch({ type: `INCREMENT` });//디스패치 increment면 state+1 증가
}}
>
+1
</Button>
<Button
variant="contained"
and
color="secondary"
onClick={() => dispatch({ type: `DECREMENT` })}//디스패치 decrement면 state-1 감소
>
-1
</Button>
</>
);
};
function App() {
return <Counter />;
}
export default App;