(리덕스를 배울때 reducer 개념이 나오게된다.)
Counter 예제를 작성하며 reducer를 사용해보자.
리듀서를 사용해서 카운터를 구현해보자.
import React, { useReducer } from "react";
function reducer(state, 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: 0 });
return (
<div>
<p>
현재 카운터 값은 <b>{state.value}</b>입니다.
</p>
<button onClick={() => dispatch({ type: "INCREMENT" })}>+1</button>
<button onClick={() => dispatch({ type: "DECREMENT" })}>-1</button>
</div>
);
};
export default Counter;
코드를 뜯어보자.!
const [state, dispatch] = useReducer(reducer, { value: 0 });
useReducer를 사용한 모양새가 useState랑 꽤나 비슷하다!
useReducer를 사용하기 위해서는 첫 번째 파라미터에는 리듀서 함수를 넣어주고(우리가 만든 reducer 함수를 넘겨주었다.),
두 번째 파라미터에는 해당 리듀서의 기본 값을 넣어주면 된다.
이 함수를 호출하면 state와 dispatch 함수를 반환한다.
여기서 state는 현재의 상태값이고, dispatch는 액션을 발생시키는 함수이다.
<button onClick={() => dispatch({ type: "INCREMENT" })}>+1</button>
<button onClick={() => dispatch({ type: "DECREMENT" })}>-1</button>
이런식으로 dispatch함수의 인자에 액션 값을 넘겨주면 리듀서 함수가 호출된다.
실행해보면 카운터가 잘 구현된 것을 볼 수 있을 것이다.
Counter 함수를 useState와 useReducer를 사용해서 구현했을 때의 차이점을 살펴보자.
이번에는 useReducer를 사용해서 Input 상태를 관리해보자.
import React, { useReducer } from "react";
function reducer(state, action) {
return {
...state,
[action.name]: action.value,
};
}
const Info = () => {
const [state, dispatch] = useReducer(reducer, { name: "", nickname: "" });
const { name, nickname } = state;
const onChange = (e) => {
dispatch(e.target);
};
return (
<div>
<div>
<input name="name" value={name} onChange={onChange} />
<input name="nickname" value={nickname} onChange={onChange} />
</div>
<div>
<b>이름 : </b> {name}
</div>
<div>
<b>닉네임 : </b>
{nickname}
</div>
</div>
);
};
export default Info;
useReducer의 액션은 어떤 값도 사용이 가능하다.
그래서 이 예제에서는 이벤트 객체가 갖고있는 e.target 값 자체를 액션 값으로 사용했다.
코드를 뜯어보자.
const [state, dispatch] = useReducer(reducer, { name: "", nickname: "" });
const onChange = (e) => {
dispatch(e.target);
};
function reducer(state, action) {
return {
...state,
[action.name]: action.value,
};
}
reducer 함수는 state를 반환하고 있다.
(기존의 state에서 변경된 부분은 값을 바꿔서 반환해주고 있다.)
Redux를 잠깐 공부했을때 리듀서의 개념을 배운 적이 있다. 굉장히 어렵다고 느꼈었는데 오늘 이렇게 useReducer를 직접 사용해보고 개념을 정리하는 과정에서 Reducer의 개념과 로직을 잘 이해할 수 있게 됐다.
특히, useState와 useReducer를 둘 다 사용해서 같은 예제를 작성하고 비교해보니 그 차이가 확실히 느껴졌고 두 Hooks의 개념이 더 와닿았다.