📌 useReducer
: 컴포넌트 내부에 새로운 state를 생성하는 React Hook
- 모든 useState는 useReducer로 대체가 가능하다.
- 사실상 useState와 거의 비슷하다.
- 상태 관리 코드를 컴포넌트 외부로 분리할 수 있다.
- : 컴포넌트 내부에는 state 생성만 해놓고
- 실제로 state를 관리하는 코드들은 Reducer라는 함수를 통해 컴포넌트 외부에서 관리하도록 코드를 분리할 수 있다.
![](https://blog.kakaocdn.net/dn/dOYOAl/btsGbUM36vz/Prt8t4idhpFi3wljLNyiqk/img.png)
![](https://blog.kakaocdn.net/dn/bjJNqG/btsGdCxSvv6/SXdZg4j7fu91zWYKQuI4E0/img.png)
📌 useReducer 구조
const [state, dispatch] = useReducer(reducer, initialArg, init)
◽인자
- reducer : 상태가 어떻게 업데이트할 지 명시한 함수
- 순수 함수여야하며, 인자로 상태와 액션을 받아야 하고, 다음 상태값을 반환해야 한다.
- 상태와 액션은 어떤 타입도 가능하다.
- initialArg : state의 초기값
- 어떤 타입의 값도 가능하다.
- 초기 상태를 계산하는 방법은 다음에 오는 init 인자에 따라 달라진다.
- init : 초기값을 반환하는 초기화 함수 (선택사항)
- 초기화 함수가 전달되지 않은 경우 ❌ - 초기 값은 initialArg 값으로 설정된다.
- 전달된 경우 ⭕ - 초기값은 init(initialArg)를 호출한 결과로 설정된다.
◽ dispatch 함수
dispatch({
type : "구분할 이름",
data : state 값을 어떻게 변화할지,
})
: 상태 변화가 있어야 한다는 사실을 알리는 함수를 반환(= dispatch)
- dispatch: 알리다, 발송하다
dispatch({
type : "INCREASE",
data : 1, // 얼만큼 증가시킬지
})
◽ Action 객체
: 인수로 전달된 요청의 내용을 담고 있는 객체
- dispatch 함수 내부의 객체
{
type : "INCREASE",
data : 1, // 얼만큼 증가시킬지
}
🔺 useReducer 사용하기
1. import로 useReducer 불러오기
import { useReducer } from "react";
2. useReducer 호출하기
- 컴포넌트 내부에서 Dispatch 함수를 호출하면,
상태 변화가 요청됨 👉 useReducer가 상태 변화를 실제로 처리하게 될 함수(직접 생성)를 호출
const [state, dispatch] = useReducer();
3. useReducer가 상태 변화를 실제로 처리하게 될 함수 만들기
- reducer: 변환기
- 상태를 실제로 변환시키는 변환기 역할
function reducer() {
}
4. 만든 함수 reducer를 useReducer의 인수로 넣기
- 초기값도 인수로 넣어서 설정 가능
const [state, dispatch] = useReducer(reducer);
📌 useReducer로 카운터(Counter) 만들기
1. 컴포넌트 생성
const Exam = () => {
...
}
2. useReducer 생성
const [state, dispatch] = useReducer(reducer, 0); // state 초기값: 0
3. 버튼의 이벤트 핸들러 함수 생성
- dispatch 함수(state 값을 어떻게 변할지) 생성
const onClickPlus = () => {
// 1. dispatch 함수가 호출됨
dispatch ({
type : "INCREASE",
data : 1,
})
// 인수: 상태가 변하길 원하는 값
}
4. reducer 함수 생성
- 인자값으로 state(초기값)와 action 객체 전달
- 조건문(if/switch)을 통해 조건에 따라 값 변경
switch(action.type) {
case "INCREASE": return state + action.data;
case "DECREASE": return state - action.data;
default: return state
// 이외의 값은 그냥 state값 반환
}
🔸 실행 과정
![](https://blog.kakaocdn.net/dn/cIj1Va/btsGdS8wmlt/usDfudA83xtIdwIxX8Zya0/img.png)
'+'(Plus) 버튼을 누르면
1. dispatch 함수가 호출됨
2. 실제 상태를 변환시키는 reducer 함수가 실행됨
- dispatch 함수의 action 객체("INCREASE", 1)가 reducer 함수의 매개변수로 전달되어 실행됨
![](https://blog.kakaocdn.net/dn/QsPZO/btsGcgI8K5a/G3GImhu0xXJr1eCl87q2cK/img.png)
3. + / - 버튼의 조건에 따라 값 변경하기
- action.type이 "INCREASE"라면 dispatch 함수가 실행됐다는 것 ➡ 버튼이 눌렸다는 것
➡ 버튼이 눌렸으면 현재 state 값에 + 1(action.date)를 해줄 것
4. reducer 함수에서 반환된 변환 값(state + action.data;)이 useReducer의 인자로 들어감
import { useReducer } from "react";
// 2. 실제 상태를 변환시키는 reducer 함수가 실행됨
function reducer(state, action) {
// state => 0, action => "INCREASE", 1
switch(action.type) {
case "INCREASE": return state + action.data;
/* action.type이 "INCREASE"라면 dispatch 함수가 실행됐다는 것 -> 버튼이 눌렸다는 것
=> 버튼이 눌렸으면 현재 state 값에 + 1(action.date)를 해줄 것 */
case "DECREASE": return state - action.data;
default: return state // 이외의 값은 그냥 state값 반환
}
}
// Exam 컴포넌트
const Exam = () => {
const [state, dispatch] = useReducer(reducer, 0); // state 초기값: 0
// + 버튼
const onClickPlus = () => {
// 1. dispatch 함수가 호출됨
dispatch ({ // dispatch 함수의 인수: 상태가 변하길 원하는 값
type : "INCREASE",
data : 1,
})
}
// - 버튼
const onClickMinus = () => {
dispatch({
type: "DECREASE",
data: 1,
})
}
return (
<div>
<h1>{state}</h1>
<button onClick={onClickPlus}>+</button>
{/* '+' 버튼 클릭 시 dispatch 함수를 호출(상태 변화를 요청) */}
<button onClick={onClickMinus}>-</button>
</div>
)
}
export default Exam;
출처
한입 크기로 잘라먹는 리액트
useReducer를 어떻게, 그리고 언제 사용할까?
useReducer의 문법과 사용법, 그리고 언제 useReducer를 사용하면 좋은지 알아보자.
eun-jee.com