[React.js] Hook(1) - useReducer

apro_xo·2021년 11월 11일
0
post-thumbnail

1. 상태 관리

상태 관리 라이브러리에는 Vuex, Redux, MobX 등이 있다. 대규모 어플리케이션을 개발하면서 많고 흩어져있는 데이터를 한 곳에 모아 관리하기 위해 쓰인다.

React도 역시 state가 많아질 수록 관리가 어려워지고, 복잡한 애플리케이션의 경우 컴포넌트로 Props를 이용해 데이터를 전달해주기에는 많은 컴포넌트 경로를 거쳐가야 할 수도 있다. 따라서 Redux를 많이 쓰긴하지만, useReducerContext API를 사용하여 어느 정도 커버는 할 수 있다고 한다👍

2. useReducer

useReducer는 useState보다 더 다양한 컴포넌트 상황에 따라 다양한 상태를 다른 값으로 업데이트해 주고 싶을 때 사용하는 Hook이다. state의 개수를 대폭 줄일 수 있다.

  • reducer 란

현재 상태, 액션 객체를 매개변수로 받아와서 새로운 상태를 반환해주는 함수

  • 기존 코드
import React, { useState, useReducer } from 'react';
import Table from './Table';

function App() {
  const [winner, setWinner] = useState('');
  const [turn, setTurn] = useState('0');
  const [tableData, setTableData] = useState('');

  return(
    <Fragment>
      <Table />
      {winner && <div>{winner}님의 승리</div>}
      </Fragment>
  )
}

useState를 이용하여 여러 state를 각각 관리하고 있으며, winner state를 컴포넌트에 렌더링하고 있다.

  • useReducer를 사용한 코드

    위의 코드를 useReducer를 이용한 코드로 바꿔보자.

import React, { useState, useReducer, useCallback } from 'react';
import Table from './Table';

const initialState = {
  winner:'',
  turn:"0",
  tableData:'',
}

const SET_WINNER = 'SET_WINNER'; // 상수 처리

const reducer = (state, action) => {
  switch(action.type) {
    case SET_WINNER:
      return {
        ...state, // 기존의 state를 복사 (spread 문법)
        winner : action.winner // 바뀌는 데이터만 덮어써주기
      }
         }
}

function App() {
  const [state, dispatch] = useReducer(reducer, initialState);
  
  const onClickTable = useCallback(()=> {
    dispatch({ type:'SET_WINNER' }, winner : '0');
  }, [])
  
  return(
    <Fragment>
      <Table onClick = {onClickTable}/>
      {state.winner && <div>{state.winner}님의 승리</div>}
      </Fragment>
  )
}

initialState는 이전에 만들었던 state를 묶어두면 된다. 관리하고 싶은 state를 묶어서 선언한다고 생각하자.

/* initialState */
const initialState = {
  winner:'',
  turn:"0",
  tableData:'',
}

그리고 useReducer를 사용하는 부분이다.

const [state, dispatch] = useReducer(reducer, initialState);

useCallback()을 사용하여 클릭이벤트핸들러 함수를 구현한다.

const onClickTable = useCallback(()=> {
    dispatch({ type:'SET_WINNER' ,winner : '0' });
  }, [])

dispatch 안에 들어가는 것은 action이라고 부른다. 따라서 액션객체를 위와 같이 만들어줘야하며, type 데이터가 있어야 한다.

dispatch한다는 것은 action을 실행하는 것과 일맥상통한다.

reducer는 함수이므로 Arrow Function의 형태로 선언하였다. reducer는 함수라는 것을 꼭 기억하자. action만있다고해서 자동으로 state가 바뀌는 것이 아니다. action을 해석해서 state를 직접 바꿔주는 역할을 하는 것이 reducer다. actiondispatch할 때 마다 reducer가 실행되며, reducer 함수는 switch문을 이용하여 아래와 같이 구현한다.

/* reducer */
const reducer = (state, action) => {
  switch(action.type) {
    case SET_WINNER:
      return {
        ...state, // 기존의 state를 복사 (spread 문법)
        winner : action.winner // 바뀌는 데이터만 덮어써주기
      }
         }
}

action의 이름은 const상수로 빼서 대문자로 사용하는 것을 추천한다.

const SET_WINNER = 'SET_WINNER'; // 상수 처리

useReducer를 사용했을 때의 가장 큰 장점은 컴포넌트 업데이트 로직을 컴포넌트 바깥으로 빼낼 수 있다는 것

따라서 context API를 사용하여 로직을 구현할 때 useReducer가 같이 많이 사용된다.

profile
유능한 프론트엔드 개발자가 되고픈 사람😀

0개의 댓글