디스패치 / 액션 / 리듀서
useReducer를 사용하면 state를 변경해야할 때 dispatch함수를 호출하고, 액션 객체를 전달해서 state를 변경한다.
- dispatch : 액션을 실행해주는 함수.
- 액션 객체 : dispatch에 전달되는 객체로 리듀서가 실행해야할 로직을 알려주는 action.type과 리듀서가 변경해야할 state값을 가지고 있다.
- reducer : 액션 객체를 해석해서 state를 직접 바꿔주는 함수. (리듀서는 dispatch가 실행될 때 마다 자동으로 호출된다.) --> reducer함수에서 반환하는 값은 새로운 state이다.
useReducer를 사용하면 state 변경 순서는 아래와 같아진다.
- 이벤트 발생
- dispatch 호출 (이벤트 객체를 만들어서 dispatch 함수 호출 시 이벤트 객체를 넘겨준다.)
- dispatch가 호출되면 자동으로 리듀서가 호출되면서 액션 객체를 해석하여 특정 로직 실행 (state변경)
reducer함수에서 주의해야할 점은 불변성을 꼭 지켜야한다는 것!
reducer함수에서 반환하는 값은 새로운 state인데 항상 새로운 객체를 만들어 바뀐 값만 바꿔줘야한다. 이를 위해 spread연산자를 활용해서 불변성을 지키자!
ACTION TYPE
- 액션 타입은 리듀서함수에서 어떤 state를 수정할 로직을 실행해야할지 결정하는 중요한 정보이다.
- 액션 타입은 상수로 따로 빼두는 것이좋다.
- 액션 타입은 대문자로 하는 것이 커뮤니티 규칙이다.
TicTacToe.jsx
import React, {useCallback, useReducer, useState} from "react";
import Table from "./Table";
//state 초기값
const initialState = {
winner : '',
turn: 'O',
tableData:[['','',''],['','',''],['','','']],
}
//액션 타입은 상수로 따로 빠두는것이 좋다.
//액션의 이름은 대문자로 하는것이 커뮤니티 규칙!
const SET_WINNER = 'SET_WINNER';
//리듀서 == 함수
const reducer = (state, action) => {
//리듀서는 액션을 디스패치 할 때마다 실행된다.
switch(action.type){
case SET_WINNER:
//state.winner = action.winner; 이렇게 하면 안된다!!!!
//우리는 항상 새로운 객체를 만들어서 바뀐 값만 바꿔줘야한다. 불변성 지켜!.
return {
...state,
winner: action.winner,
}
}
}
const TicTacToe = () => {
/*
const [winner, setWinner] = useState('');
const [turn, setTurn] = useState('O');
const [tableData, setTableData] = useState([['','',''],['','',''],['','','']]);
*/
const [state, dispatch] = useReducer(reducer, initialState);
//컴포넌트에 있는 함수들은 다 useCallback으로 감싸주자.
const onClickTable = useCallback(()=>{
//dispatch는 액션을 실행해주는 함수이다. dispatch에 전달되는 값은 액션객체이다.
//액션 객체를 해석해서 state를 직접 바꿔주는 역할을 하는 것이 리듀서이다.
dispatch({type:SET_WINNER, winner:'O'});
},[]);
return(
<>
<Table onClick={onClickTable} tableData={state.tableData}/>
{
state.winner && <div>{state.winner}님의 승리</div>
}
</>
);
}
export default TicTacToe;
Table.jsx
import React from 'react';
import Tr from "./Tr";
const Table = ({onClick, tableData}) => {
return (
<table onClick={onClick}>
{Array(tableData.length).fill().map((tr,i)=><Tr rowData={tableData[i]}/>)}
</table>
);
};
export default Table;
Tr.jsx
import React from 'react';
import Td from "./Td";
const Tr = ({rowData}) => {
return (
<tr>
{
Array(rowData.length).fill().map((td)=><Td/>)
}
</tr>
);
};
export default Tr;
'코딩이야기 > 인터넷 강의' 카테고리의 다른 글
section6 7-3.action만들어 dispatch하기 (0) | 2024.06.16 |
---|---|
틱택토 개인코드 (0) | 2024.06.14 |
section6 7-1. 틱택토와 useRedcuer 소개 (0) | 2024.06.12 |
seciton5 6-4. useEffect로 업데이트 감지하기 (0) | 2024.06.10 |
section5. 6-1 로또 추첨기 컴포넌트 (0) | 2024.06.04 |