useReducer

abi hong·2023년 7월 27일
0

Frontend

목록 보기
3/12

숫자를 count하는 기능을 만들어보자!

useState를 사용하기

export default function App() {
  const [count, setCount] = useState(0);
  function down() {
    setCount(count - 1);
  }
  function reset() {
    setCount(0);
  }
  function up() {
    setCount(count + 1);
  }
  return (
    <div>
      <input type="button" value="-" onClick={down} />
      <input type="button" value="0" onClick={reset} />
      <input type="button" value="+" onClick={up} />
      <span>{count}</span>
    </div>
  );
}

useState를 사용하게 되면...

이 기능을 은행과 비교하면,

  • state == 장부
  • event == 고객

고객이 장부를 직접 기록하는 방식,
즉 event가 발생했을 때, 고객이 직접 state 값을 바꾸는 방식이다.

코드를 살펴보면, 원래 count가 0이고 count 값을 바꾸고 싶을 때, setCount()를 사용한다.
고객이 count 값을 바꾸고 싶을 때마다, 직접 값을 바꿔준다.

But, 만약.. 고객이 1억명일때는?

고객이 1억명이고 장부의 state들이 아주 많고 복잡하면... 이때 고객이 직접 state를 바꾸기보다 action(주문)을 취하는 것이 낫다!

useReducer

const [state, dispatch] = useReducer(reducer, initialArg, init?)

  • action : 사용자는 dispatch()를 호출하여 action을 취함
    → 직접 값을 바꾸는 것이 아님!!!
function down() {
	dispatch('DOWN');
}
function reset() {
    dispatch('RESET');
}
function up() {
    dispatch('UP');
}
  • dispatch : action을 받고 reducer가 실행됨!!
  • reducer : 들어온 action과 기존의 state를 비교해서 새로운 state를 update
    → reducer를 사용하면 state를 직접 사용자가 사용하는 것이 아닌 action(주문) 값만 주고 그 state에 대한 구체적인 처리는 countReducer() 함수가 독점적으로 처리함
export default function App() {
  function countReducer(oldCount, action) {
    if (action === 'UP') {
      return oldCount + 1;
    } else if (action === 'DOWN') {
      return oldCount - 1;
    } else if (action === 'RESET') {
      return 0;
    }
  }
  const [count, countDispatch] = useReducer(countReducer, 0); // 1: reducer 함수, 2: 초기값
  function down() {
    countDispatch('DOWN');
  }
  function reset() {
    countDispatch('RESET');
  }
  function up() {
    countDispatch('UP');
  }
  return (
    <div>
      <input type="button" value="-" onClick={down} />
      <input type="button" value="0" onClick={reset} />
      <input type="button" value="+" onClick={up} />
      <span>{count}</span>
    </div>
  );
}

하나를 더 추가해서 구현해보자~

number 값 만큼 count가 증가하려면??

number 값은 useState를 이용할 것

이때, reducer()가 number를 직접 사용하면 좋지 않다.
→ reducer()의 경우, input과 output 값만으로 함수의 동작이 달라져야지 이 함수가 직접 number에 접근하면 좋지 않다.
(= setNumber로 값을 사용하는건 좋지 않다는 뜻!)

따라서 action을 줄 때, number 값을 전달하면 좋다.

export default function App() {
  const [count, countDispatch] = useReducer(countReducer, 0); 
  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;
    }
  }

  function down() {
    countDispatch({ type: 'DOWN', number: number });
  }
  function reset() { 
    countDispatch({ type: 'RESET', number: number });
  }
  function up() {
    countDispatch({ type: 'UP', 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>
  );
}

useReducer를 사용하면

  • state를 사용하는 곳에서는 복잡한 로직을 처리하지 않아도 되고
  • 복잡한 상태를 바꾸는 것은 전문화 된 함수(= reducer())가 처리할 수 있다.

0개의 댓글