useReducer 훅이란?
- useState를 대체할 수 있는 함수이다.
- React에서 컴포넌트의 상태 관리를 위해 기본적으로 가장 많이 쓰이는 hook은 state이다.
- reducer는 이전 상태와 Action을 합쳐, 새로운 state를 만드는 조작을 말한다.
- 좀 더 복잡한 상태 관리가 필요한 경우 reducer를 사용할 수 있다. (콜백대신 dispatch를 전달할 수 있기 때문이라고 볼 수 있다.)
useReducer를 사용하기 위한 구성요소들은 다음과 같다.
useReducer 함수
import React, { useReducer } from "react";
const [state, dispatch] = useReducer(reducer, initialState, init);
- state
: 컴포넌트에서 사용할 상태
- dispatch 함수
: 첫 번째 인자인 reducer 함수를 실행시킨다.
컴포넌트 외부에서 state의 업데이트를 일으키기 위해 사용하는 함수
- reducer 함수
: 컴포넌트 외부에서 state를 업데이트 하는 함수
현재 state, action 객체를 인자로 받아, 기존의 state를 대체하여 새로운 state를 반환하는 함수
- initialState
: 초기 state
- init
: 초기 함수 (초기 state를 조금 지연해서 생성하기 위해 사용)
dispatch 함수
reducer 함수를 실행 시킨다.
action 객체를 인자로 받으며 action 객체는 어떤 행동인지를 나타내는 type 속성과 해당 행동과 관련된 데이터(payload)를 담고 있다.
action을 이용하여 컴포넌트 내에서 state의 업데이트를 일으킨다.
※ action은 보통 하기 샘플 예시와 같이 사용 한다. ※
ex) action type만 정의하여 사용
<button onClick={() => dispatch({ type: "INCREMENT" })}>증가</button>
ex) action type과 데이터를 정의하여 사용
<button onClick={() => dispatch({ type: "INCREMENT", payload: 1 })}>증가</button>
3. reducer 함수
상기 dispatch 함수에 의해 실행되며, 컴포넌트 외부에서 state를 업데이트 하는 로직을 담당한다.
함수의 인자로는 state와 action을 받게 된다.
state와 action을 활용하여 새로운 state를 반환한다.
ex1) action type만 정의하여 사용
function reducer(state, action) {
switch (action.type) {
case "INCREMENT":
return { count: state.count + 1 };
case "DECREMENT":
return { count: state.count - 1 };
default:
throw new Error("unsupported action type: ", action.type);
}
}
ex2) action type과 데이터를 정의하여 사용
function reducer(state, action) {
switch (action.type) {
case "INCREMENT":
return { count: state.count + action.payload };
case "DECREMENT":
return { count: state.count - action.payload };
default:
throw new Error("unsupported action type: ", action.type);
}
}
※ count 함수를 통해 사용 방법을 알아 보고, state를 활용한 예시랑 비교해보기 ※
ex1) init 함수를 사용하지 않는 counter 예시
import React, { useReducer } from "react";
function reducer(state, action) {
switch (action.type) {
case "INCREMENT":
return { count: state.count + action.payload };
case "DECREMENT":
return { count: state.count - action.payload };
default:
throw new Error("unsupported action type: ", action.type);
}
}
const Counter = () => {
const initialState = { count: 0 };
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
<h2>{state.count}</h2>
<button onClick={() => dispatch({ type: "INCREMENT", payload: 1 })}>
증가
</button>
<button onClick={() => dispatch({ type: "DECREMENT", payload: 1 })}>
감소
</button>
<button onClick={() => dispatch({ type: "kkkkkkkkk", payload: 1 })}>
에러
</button>
</>
);
};
export default Counter;
ex2) init 함수를 사용하여 counter 예시
초기 state를 조금 지연해서 생성할 수 있다.
init 함수를 세 번째 인자로 전달하면, 초기 state는 init(initialArg)에 설정될 것이다.
import React, { useReducer } from "react";
function init(initialState) {
return { count: initialState };
}
function reducer(state, action) {
switch (action.type) {
case "INCREMENT":
return { count: state.count + action.payload };
case "DECREMENT":
return { count: state.count - action.payload };
case "RESET":
return init(action.payload);
default:
throw new Error("unsupported action type: ", action.type);
}
}
const Counter = ({ initialCount }) => {
const [state, dispatch] = useReducer(reducer, initialCount, init);
return (
<>
<h2>{state.count}</h2>
<button onClick={() => dispatch({ type: "RESET", payload: 0 })}>
초기화
</button>
<button onClick={() => dispatch({ type: "INCREMENT", payload: 1 })}>
증가
</button>
<button onClick={() => dispatch({ type: "DECREMENT", payload: 1 })}>
감소
</button>
<button onClick={() => dispatch({ type: "kkkkkkkkk", payload: 1 })}>
에러
</button>
</>
);
};
export default Counter;
ex) useState 사용
import React, { useState } from "react";
const Counter = ({ initialCount }) => {
const initial = initialCount ? initialCount : 0;
const [count, setCount] = useState(initial);
const onIncrease = () => {
setCount((count) => count + 1);
};
const onDecrease = () => {
setCount((count) => count - 1);
};
return (
<>
<h2>Count: {count}</h2>
<button onClick={() => setCount(initial)}>초기화</button>
<button onClick={onIncrease}>증가</button>
<button onClick={onDecrease}>감소</button>
</>
);
};
export default Counter;
useReducer를 활용 한다면 좀 더 복잡한 프로세스를 처리할 수 있을 것이다.
그리고 state를 변경하는 부분(Count를 감소, 증가 시키는 부분)이 useState와 같은 경우 내부에 위치하며, useReducer와 같은 경우 외부에 위치한다.
ex) useState

ex) useReducer

'Framework | Library > React.js' 카테고리의 다른 글
[React] 이벤트 핸들러에 인자 전달하기 (0) | 2022.07.12 |
---|---|
[React] event handling 하는 법 (0) | 2022.07.12 |
[React] Virtual DOM(VDOM)과 Diffing 알고리즘 (0) | 2022.07.12 |
[React] props (0) | 2022.07.11 |