리액트에서 상태값을 변경하는 2가지 방법
- setter 함수를 직접 제공
- setter 함수를 제공하지 않고 dispatch 함수를 제공 - Redux 방식
dispatch 함수 이용 예
dispatch({ 액션 객체 }) 형태로 작성한다.
dispatch({ type: "INCREMENT", payload: 1 })
액션 객체에는 type
이라는 키가 필수로 포함되어야 한다. type 키 값으로는 해당 dispatch 함수의 type을 문자열로 명시한다.
type을 제외하고 나머지는 자유롭게 값 지정 가능하나, 보통 payload
키를 넣어 type에 대한 값을 지정한다.
위 예시에서 type: "INCREMENT"
에 payload: 1
이라는 것은 상태값을 1씩 증가시키겠다는 의미다.
useReducer 훅
useReducer 훅을 이용해 컴포넌트 상태값을 리덕스의 리듀스처럼 관리할 수 있다.
(참고 - 리듀서란 dispatch 함수로부터 액션 객체를 받아서 상태값에 대한 setter 로직을 구현한 함수를 말한다.)
먼저 리듀서를 사용하지 않은 예시다. input 란에 값을 입력하면 myname, age 상태값에 바로 반영하는 로직이다.
const App = () => {
const [person, setPerson] = useState({ myname: '', age: '' });
const { myname, age } = person;
return (
<div>
myname: {myname}, age: {age}
<br />
<input
type="text"
placeholder="name"
onChange={(e) => setPerson({age, myname: e.target.value})} />
<input
type="text"
placeholder="age"
onChange={(e) => setPerson({myname, age: e.target.value})} />
</div>
// e.target에서 target이란 현재 element를 나타내고,
// e.target.value는 현재값을 나타냄
);
};
export default App;
useReducer 훅을 사용한다면 이렇게 바꿀 수 있다.
const reducer = (prevState, action) => {
// type을 받아와서
const { type, value } = action;
// type에 따라
if ( type === 'SET_NAME' ) {
// 적절히 상태값 세팅
return { ...prevState, myname: value };
}
else if (type === 'SET_AGE') {
return { ...prevState, age: value };
}
return prevState;
};
const App = () => {
const [state, dispatch] = useReducer(reducer, { myame: '', age: '' });
const { myname, age } = state;
const onChange = (e) => {
const { name: type, value } = e.target;
dispatch({ type, value });
};
return (
<div>
myname: {myname}, age: {age}
<br />
<input
type="text"
name="SET_NAME"
placeholder="name"
onChange={onChange} />
<input
type="text"
name="SET_AGE"
placeholder="age"
onChange={onChange} />
</div>
);
};
export default App;