리액트 - 7

JiWOn·2021년 12월 6일
0

🔗강의자료 주소


틱택토와 useReducer

useReducer

  • 리덕스를 쓸 필요 없는 소규모 앱에서는 useReducer컨텍스트 API로 대체 가능
    : 근데 비동기 부분 처리를 위해 결국 리덕스를 써야함.

틱택토

  • 테이블 하나의 컴포넌트로 > tr를 하나의 컴포넌트 > td를 컴포넌트로 보기
  • useStatewinnerturn, tableData가 필요.
    - tableData는 3x3으로 만들어주기
  • useStatTicTacToe 파일에서 관리하는데 실제 클릭하는 건 Td임. (중간에 TableTr이 껴있음..)
    - 해결하기 위해 컨텍스트 API 사용하긴 함.
    • 오늘은 useReducer 사용

useReducer

  • useReducer (reducer, initialState, (지연초기화));
  • initialState는 말 그대로 State를 설정해줌. 따로 const로 선언해주기
  • reducer = 함수
    • 줄이는 함수
    • stateaction의 매개변수를 받음.
    • state를 어떻게 바꿀지 적어줌.

reducer, action, dispatch의 관계

  • state에서 initialState를 만들어 주었기 때문에 state 붙여줘야함
  • onClick 이벤트를 만들 땐 onClickTable = useCallback
    - 컴포넌트에 넣는 함수들은 useCallback
    • 테이블을 클릭하면 winner를 'O'로 바꿀 때, dispatch 사용

dispatch

  • dispatch 안에 들어가는 건 action 객체
dispatch({ type: 'SET_WINNER', winner:'O'});

action 객체 : { type: 'SET_WINNER', winner:'O'}
dispatch로 실행된다.

  • action만 있다고해서 자동으로 state가 바뀌는 건 아님.
    : action을 해석해서 state를 직접 바꿔주는 역할 => Reducer

Reducer

const reducer = (state, action) =>{
  switch (action.type){
    case 'SET_WINNER':
      // state.winner = action.winner; 이렇게 하면 안됨!!!
      return {
        ...state, // 새로운 객체를 만들어야 함. 얕은 복사
        winner: action.winner, 
        // 바뀔 부분만 새롭게 바꿔줌. => 불변성
      };
  }
};
  • 기존의 state에서 바뀔 부분만 바꿔주는
  • 대부분의 action 이름은 대문자로

action 만들어 dispatch하기

  • 클릭했을 때 몇번째 칸인지 맞추기
    - table에서 i 가 몇번째 row 인덱스인지 알려줌.
{Array(tableData.length).fill().map((tr,i) => (
  <Tr rowIndex = {i} rowData = {tableData[i]} />))}
  • tr에서 i 가 몇번째 cell 인덱스인지 알려줌
    • 이렇게 정의된 i들을 td에서 사용 가능
{Array(rowData.length).fill().map((td, i) => (
      <Td rowIndex={rowIndex} cellIndex = {i}>{''}</Td>))}
  • cell을 클릭했을 때 'O'가 뜨게
    • dispatch 이용해서 action을 만듬 => CLICK_CELL
    • TicTacToe에 reducer에서 새로 추가해주면 됨.
      - 얕은 복사로 불변성을 지킬수 있음.
case CLCIK_CELL: {
  const tableData = [...state.tableData]; //기존의 테이블 데이터를 
  //얕은 복사해줌
  tableData[action.row] = [...tableData[action.row]];
//객체가 있으면 얕은 복사 필수
// immer라는 라이브러리로 가독성 해결
  tableData[action.row][action.cell] = state.turn;
  return {
    ...state,
    tableData,
  };
}
  • 새로운 action을 만들때 전역변수로 만들어줘야하기 때문에 export const로 정의해줘야함.

  • turn 바꾸기 - 칸을 누른다음에 턴이 바뀜

case CHANGE_TURN: {
  return {
    ...state,
    turn: state.turn === 'O' ? 'X' : 'O',
  };
}
  • dispatchTicTacToe에서 갖고있기 때문에 td까지 넘겨줘야함.

틱택토 구현하기

  • state는 비동기이고 비동기인 state를 처리하려고 한다면 useEffect를 사용함!

최적화 하기

  • 셀 하나 눌렀는데 9개의 셀이 변화한다고 보임
  • 해결하기위해서 useEffect, useRef를 넣어 원인 찾기
  • 각종 props를 넣기
const ref = useRef([]);
useEffect(() => {
  consol.log(rowIndex === ref.current[0],rowIndex === ref.current[1],
rowIndex === ref.current[2],rowIndex === ref.current[3]);
  //rowIndex, cellIndex, dispatch, cellData 안 바뀔 때가 있어서 
  //이를 파악하기 위함
  ref.current = [rowIndex, cellIndex, dispatch, cellData]; //계속 바뀜.
}, [rowIndex, cellIndex, dispatch, cellData])
  • react.memo를 이용하는게 쉬움

  • useMemo 컴포넌트 자체를 기억해버림.

0개의 댓글

관련 채용 정보