useReducer는 component 내부에 새로운 State를 생성하는 React Hook이다.모든 useState는 useReducer로 대체할 수 있다. useState와의 차이점은 상태 관리 코드를 component 외부로 분리할 수 있다.

useState를 사용하면 내부에 상태 관리 코드를 작성해야한다.

useReducer를 사용하면 State 생성만 해놓고, reducer라는 함수를 통해 외부에서 상태 관리 코드를 작성할 수 있다.

기존의 코드를 보면 useState를 사용해서 반드시 상태 관리하는 코드 onCreate, onUpdate, onDelete들이 App Component 내부에 있어야 했다. 왜냐하면 State에 접근하는 setTodos함수는 App component 외부에서 접근할 수 없기 때문이다.
지금은 상태 관리 코드가 짧아서 괜찮은데, 훨씬 더 복잡한 상태 관리를 하거나, 코드가 길어질 경우 유지보수와 가독성이 떨어질 수 있다.
component의 주된 목적인 UI를 렌더링하는 것인데, 상태 관리 코드가 길어지게 되면 주객이 전도된 것이다.
따라서 component 외부에 상태 관리 코드를 분리하기 위해 useReducer를 이용한다.

Exam이라는 카운트 앱을 하나 만들어주고 useReducer를 import해서 state와 dispatch를 작성해준다.
dispatch 함수는 상태 변화를 요청하기만 하는 함수다.
component 내부에서 dispatch 함수를 호출하게 되면 상태변화가 요청이 되고, 그러면 useReducer가 상태 변화를 실제로 처리하게 될 함수를 호출하게 된다.


변환기라는 뜻을 가진 reducer 함수를 Exam component 밖에 만들어주고, useReducer 첫번째 매개변수로 reducer 함수를 넣어준다.
reducer 함수가 상태를 실제로 변화시키는 함수이다.
useReducer 함수의 두번째 매개변수로는 초기값을 전달한다.
h1 태그 안에 state 값을 렌더링하게 해주면 된다.

버튼을 클릭했을 때, dispatch 함수를 통해 상태변화를 요청하면 된다.
버튼을 클릭했을 때 연결할 onClickPlus 함수를 만들어준다. 내부에 dispatch를 호출하게 만들고, 매개변수로는 어떻게 변화시킬지에 대한 type을 increase, 얼마나 데이터를 변화시킬 것인지에 대한 data를 1만큼 객체형태로 준다. 이것을 action 객체라고 한다.

외부의 reducer 함수에 첫번째 인자로 state, 두번째 인자로는 action을 주고 console.log를 찍어보면 다음과 같다.


useReducer에서 새로운 state 값을 반환해주면 state의 값을 바꿔준다. 조건문으로 action.type이 INCREASE가 들어오면, 기존의 state에 action.data를 더해준 것을 return 해주면 된다.


같은 방식으로 -버튼을 만들고, onClickMinus 함수에 액션 객체의 type을 DECREASE, data를 -1을 하고, 외부의 reducer 함수에 조건문을 작성해주면 다음과 같이 -버튼도 구현할 수 있다.

보통 액션 객체의 type이 많아지면 if보다는 switch를 사용하는 게 일반적이다.