이번 시간에는 useReducer에 대해 알아보겠습니다.
useReducer도 useState처럼 상태값을 관리하는 훅입니다.
일단, useState는 간단한 상태값들을 관리하기엔 매우 편합니다.
하지만 상태값들을 여러개 줘야하고, 그 값들을 처리하는 방식이 다양해지면 다양해질수록 최적화 문제에 있어서 좀 관리가 안좋아 질 수도 있습니다.
때문에 다양한 상황에 있을 수록 다양하게 변화 시킬 수 있는 useReducer를 사용해주는 것이 좋다고합니다.
useState와 useReducer의 문법 차이를 알아보겠습니다.
예를들어, 아이디와 비밀번호를 받아서 상태값을 변경 시키는 상황이 있다 해봅시다.
import React, { useReducer, useState } from "react";
function App() {
//id,password 프로퍼티를 받는 account state 생성
const [accout, setAccount] = useState({
id: "",
password: "",
});
//change가 일어날때마다 해당 네임 속성값을 가진 value값들을 accout값에 설정
const handleAccount = (e) => {
setAccount({
...accout,
[e.target.name]: e.target.value,
});
};
//설정된 account 값들의 프로퍼티 값들을 해체할당
const { id, password } = accout;
return (
<div className="App">
<div>
<input
name="id"
placeholder="아이디를 입력하세요"
onChange={handleAccount}
/>
<input
name="password"
placeholder="비밀번호를 입력하세요"
onChange={handleAccount}
/>
</div>
<div>
<p>내가 입력한 아이디는 : {id}</p>
<p>내가 입력한 비밀번호는 : {password}</p>
</div>
</div>
);
}
export default App;
import React, { useReducer, useState } from "react";
//action에 따라 안에 데이터를 어떻게 변화시킬지 설정
function reducer(state, action) {
return {
...state,
[action.name]: action.value,
};
}
function App() {
//reducer뒤에는 상태 기본값을 씀
const [state, dispatch] = useReducer(reducer, {
id: "",
password: "",
});
const handleAccount = (e) => {
//데이터를 변화시키기 위한 동작을 할 dispatch
//action값을 보냄
dispatch(e.target);
};
const { id, password } = state;
return (
<div className="App">
<div>
<input
name="id"
placeholder="아이디를 입력하세요"
onChange={handleAccount}
/>
<input
name="password"
placeholder="비밀번호를 입력하세요"
onChange={handleAccount}
/>
</div>
<div>
<p>내가 입력한 아이디는 : {id}</p>
<p>내가 입력한 비밀번호는 : {password}</p>
</div>
</div>
);
}
export default App;
1.컴포넌트 선언문 위에 reducer를 선언하여 action값을 받아서 어떤식으로 상태값을 셋팅할지 선언합니다.
2. useReducer훅을 사용하여 reducer를 연결해주고, state값의 기본 형태를 만들어줍니다.
3. 발생시키고 싶은 이벤트함수를 만들어주고 dispatch를 사용하여 reducer에 action값을 넘겨줍니다.
4.reducer에서 action값을 받아서 state값을 처리해줍니다.
//dispatch로 e.target을 보냈기때문에 reducer에서 [e.target.name] : e.target.value 의 형태로 들어가게되는것입니다.
++ dispatch 안에 type같은 속성값들을 지정하고 그 속성값들마다 return값을 다르게 설정하여 여러 상황에서 다른 return 값들을 출력할 수 있습니다.
--> 사실 이것이 useReducer를 사용하는 핵심적인 이유라고 할 수 있습니다! 아래가 그에 대한 예시입니다.
import React, { useReducer, useState } from "react";
//action에 따라 안에 데이터를 어떻게 변화시킬지 설정
function reducer(state, action) {
switch (action.type) {
//타입이 calAvg면 실행
case "calAvg":
return {
...state,
num1: state.num1,
num2: state.num2,
avg: (Number(state.num1) + Number(state.num2)) / 2,
};
//타입이 아무것도 안오면 그냥 기본값 실행
default:
return {
...state,
[action.name]: action.value,
};
}
}
function App() {
const [state, dispatch] = useReducer(reducer, {
num1: "",
num2: "",
});
const { num1, num2, avg } = state;
const onChange = (e) => {
dispatch(e.target);
};
const onCalAvg = () => {
dispatch({ type: "calAvg" });
};
return (
<div className="App">
<input
name="num1"
placeholder="더하고 싶은 첫번째 숫자를 적어주세요 :)"
onChange={onChange}
/>
<input
name="num2"
placeholder="더하고 싶은 두번째 숫자를 적어주세요 :)"
onChange={onChange}
/>
<button onClick={onCalAvg}> 평균 값 구하기 </button>
<div>
<p>
{num1} + {num2} = {avg} 입니다
</p>
</div>
</div>
);
}
export default App;
이런식으로 기본값과 타입을 지정하여 여러개의 setState를 안만들고,
각기 다른 이벤트를 설정할 수 있습니다!!