useState를 여러개를 정의해서 사용하다보면, 불편한 점이 있다.
일단 모든 state를 각각 정의해줘야 하고, 각각의 state를 별도로 관리하는 쉽지 않다.
state 내 데이터가 복잡해지면, 초기화 하는 것도 쉽지 않다.
그래서, 복잡한 state 관리는 useReducer를 사용하는 것이 좋다.
<<사용 방법>>
1. 선언
const [state, dispatch] = useReducer(reducer, initialState);
2. reducer 및 initialState 정의
: reducer는 각 상태 타입마다의 리턴값을 정의해주어야 한다. 따라서, 실제 reducer의 실행 부분이라고 할 수 있다.
const initialState = {
winner: null,
turn: "O",
const tableData: [
["", "", ""],
["", "", ""],
["", "", ""],
],
};
const reducer = (state, action) => {
switch(action.type) {
case 'SET_WINNER':
return {
...state,
winner: action.winner,
}; // 불변성
}
};
3. 상태 타입에 따른 action 객체 생성 : dispatch 키워드를 활용해서 사용한다.
const onClickTable = useCallback(() => {
// action 객체 생성
dispatch({type: 'SET_WINNER', winner: 'O'});
}, []);
(별첨) useReducer를 사용하기 전에 useState만 사용한 코드는 다음과 같다.
const [winner, setWinner] = useState(null);
const [turn, setTurn] = useState("O");
const [tableData, setTableData] = useState([
["", "", ""],
["", "", ""],
["", "", ""],
]);
[useReducer는 비동기 state를 내부적으로 사용한다.] -- [Redux는 동기 state 사용]
- 비동기 state를 처리하기 위해선, useEffect를 반드시 사용해야 한다.
(예제)
틱텍토 게임을 만드는 경우, 결과 판단을 어디서 할까 고민이 된다.
동기형이라면, 셀을 클릭했을 때 결과를 판단하면 될 것 같다.
하지만, 비동기라면 셀을 클릭했을 때 Turn의 값이 다를 수 있다.
reducer와 같은 비동기 state의 경우, useEffect의 didUpdated를 활용해서 작성하자.
최근댓글