useReducer 생활코딩 강의 정리

혜미·2022년 8월 18일

React

목록 보기
1/10
post-thumbnail

생활코딩 강의 링크

useState와 useReducer 차이점

- useState

고객이 장부 수정하는 방법을 배워서 (setState를 이용해서) 직접 은행 장부를 수정

근데 고객이 1억명이면, 고객 한 명 한 명이 장부에 기록하는 방법을 모두 안다? 말이 안 된다.

- useReducer

회계 담당자가 들어온 주문 (action) 과 기존의 장부 내용 (state) 을 이용해서 장부의 새 값을 만들어낸다.

useReducer는 ( 비유하자면 ) 은행을 만드는 코드다!

useReducer(은행)과 직원들 소개👵🧓🏿👩🏻‍

useReducer는 ( 비유하자면 ) 은행을 만드는 코드다!

즉,

  • 회계 담당자 (countReducer)
  • 장부의 초기값 (0)
  • 장부 (count)
  • 창구 직원 (countDispatch)

이런 요소들을 만드는 은행의 설립자다!

  1. 고객은 직접 장부를 기록하지 않고 창구 직원 (countDispatch) 에게 주문 (action) 만 한다.
  2. 그럼 창구 직원 (countDispatch) 이 주문을 받아서 회계 직원 (countReducer) 에게 넘겨 주고
  3. 회계 직원은 들어온 주문 (action) 과 기존의 장부 내용 (state)를 이용해서 장부의 새 값을 만들어낸다.

useReducer 사용법

파라미터

  const [count, countDispatch] = ✨useReducer(countReducer, 0);

은행에는 2개의 파라미터가 필요한데,

  • 첫 번째 파라미터: countReducer는 회계 직원 (구체적으로는 함수다)
  • 두 번째 파라미터: 이 장부의 초기값

count, countDispatch

  const [✨count, countDispatch✨] = useReducer(countReducer, 0);

count의 값은 0으로 출발하고(아래 코드의 경우), 장부 변경할 때는 countDispatch (창구 직원) 를 사용한다.

고객 입장

고객은 직접 장부를 기록하지 않고 창구 직원 (countDispatch) 에게 주문 (action) 만 한다.

countDispatch('액션명')

이라는 명령을 내리면 countReducer가 호출되도록 약속되어 있다.

countReducer

function countReducer(oldCount, action) {
    if (action.type === 'UP') {
      return oldCount + action.number;
    } else if (action.type === 'DOWN') {
      return oldCount - action.number;
    } else if (action.type === "RESET") {
      return 0;
    }
  }

회계 직원이 주문과 장부의 이전 상태를 보고 장부의 새로운 상태를 만들 듯, countReducer도 마찬가지다.

주문(action)이 'UP'이면 이전 카운트 값에 number를 더한 값을 리턴하고, 그 리턴값이 새로운 count가 된다.

reducer의 장점

💡사용하는 측에서는 복잡한 로직을 처리하지 않아도 된다.

복잡한 상태를 바꾸는 작업은 전문화된 함수(countReducer == 회계 담당자)가 처리할 수 있게 된다.

💡💡 이전 값과 이후의 값이 상당히 긴밀히 연관되어 있을 때 reducer를 사용하면 상태를 변경시키는 과정을 reducer 함수 안에 은닉할 수 있다.
(reducer를 쓰는 아주 중요한 이유다!)

코드 보고 이해하기

import React, { useReducer, useState } from "https://cdn.skypack.dev/react@17.0.1";
import * as ReactDOM from "https://cdn.skypack.dev/react-dom@17.0.1";

function App() {
  const [number, setNumber] = useState(1);
  
  function countReducer(oldCount, action) {
    if (action.type === 'UP') {
      return oldCount + action.number;
    } else if (action.type === 'DOWN') {
      return oldCount - action.number;
    } else if (action.type === "RESET") {
      return 0;
    }
  }
  
  const [count, countDispatch] = useReducer(countReducer, 0);
  function down() {
    countDispatch({type: 'DOWN', number: number})
  }
  function up() {
    countDispatch({type: 'UP', number: number})
  }
  function reset() {
    countDispatch({type: 'RESET', number: number})
  }
  
  function changeNumber(event) {
    setNumber(Number(event.target.value));
  }
  
  
  
  return (
    <div>
      <input type="button" value="-" onClick={down} />
      <input type="button" value="0" onClick={reset} />
      <input type="button" value="+" onClick={up} />
      <input type="text" value={number} onChange={changeNumber} />
      <span>{count}</span>
    </div>
  );
  
}

ReactDOM.render(<App />, document.getElementById('root'));

위 코드처럼 useState와 useReducer를 같이 쓸 수 있다.

이때 useReducer 안에서, useState가 관리하는 state 값이 필요할 때 직접 이 state를 참조하는 건 좋지 않다.

왜냐면 reducer 함수는 순수(pure) 함수기 때문에, input (파라미터)과 output(리턴값)에 의해서만 함수의 동작이 달라져야 하기 때문이다. 외부 요인의 영향을 받으면 안 된다.

그래서 reducer 함수에 파라미터로 전달하는 action을 객체로 바꿔서 그 객체 안에다가 state를 전달하고 있다.

0개의 댓글