[TIL] 23.05.02

Minkyu Shin·2023년 5월 2일
0

TIL

목록 보기
20/44
post-thumbnail

오늘의 나는 무엇을 잘했을까?

리액트 useState useReducer Hook 각각을 이해하는데 심혈을 기울였던 하루였다. 다양한 자료를 찾아보고 책으로 실습을 따라 하다보니 어느 정도 이해는 된 것 같다. 오늘처럼 한 단계씩 차근차근 공부를 해 나아가야 진정 내 것이 될 것 같다는 생각이 들었다. 진도에 너무 매몰되지 말자.

오늘의 나는 무엇을 배웠을까?

1. useReducer

useState 를 활용하여 컴포넌트의 상태를 업데이트 할 때 업데이트 로직은 컴포넌트 내에 위치해 있어야 한다. 상태와 상태 변화 코드를 모두 컴포넌트 안에서 선언하기 때문이다. 하지만 useReducer 를 활용하면 상태를 관리할 때 상태 업데이트 로직을 컴포넌트에서 분리시켜 바깥에 작성하거나 심지어는 다른 파일에 작성 후 불러와 활용할 수도 있게 된다. 이를 상태 변화 코드의 분리 라고 말할 수 있다. 분리의 이유는 컴포넌트 내에 너무 많은 상태 변화 코드가 있으면 가독성을 해쳐 유지 보수를 어렵게 하기 때문이다.

useReducer 함수도 리액트 Hook의 한 종류이다.
useReducer 함수를 사용하는 문법을 알아보자.

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

useReducer 함수는 인수로 상태 변화 함수인 reducer 함수와 상태의 초깃값을 받는다. 그리고 첫 요소가 상태 변수이고 두번째 요소가 상태 변화 촉발 함수 dispatch 인 배열을 반환한다. 위 코드에서는 이를 구조 분해 하여 각각 변수에 담아 주었다.

dispatch 는 첫번째 매개변수로 액션 객체를 받아 reducer 함수를 호출하여 액션 객체를 전달해 주는 함수이다.

그렇다면 reducer 함수는 무엇일까?

function reducer(state, action) {
  // 새로운 상태를 만드는 로직
  // const nextState = ~~
  return nextState;
}

reducer는 현재 상태와 액션 객체를 매개변수로 받아 새로운 상태를 반환해 주는 함수이다. 반환된 새로운 상태는 곧 컴포넌트가 지닐 새로운 상태가 되며 컴포넌트는 해당 상태로 리렌더링 된다.
액션 객체는 업데이트를 위한 정보를 가지고 있는데 주로 type 필드와 그 외의 필요한 데이터를 가진 객체 형태로 사용된다. 예시를 살펴 보면,

{
  type: 'ADD_TODO',
  payload: {
    id: 1,
    text: '할 일 1'
  }
}

위 액션 객체의 type 필드는 액션의 종류를 나타내고, payload 는 액션이 수행될 때 필요한 데이터를 담고 있다.
useReducer 함수에서는 액션 객체의 type 필드를 활용하여 어떤 작업을 수행할지 결정하고, 그 작업에 필요한 데이터를 액션 객체에 담아 reducer 함수에 전달한다.

2. useReducer 함수와 useState 함수의 비교

앞서서 useReducer 함수를 사용하는 이유는 상태 업데이트 로직을 컴포넌트 외부에서 관리하기 위함이라고 정리해 보았다. 사실 이게 무슨 뜻인지 잘 와닿지 않기 때문에 각 함수를 사용한 코드를 비교해 보며 알아보자.

먼저 useState 함수를 활용한 카운터 예시이다.

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(count + 1);
  }

  const decrement = () => {
    setCount(count - 1);
  }

  return (
    <div>
      <h1>{count}</h1>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );
}

지금까지 사용해왔던 것과 동일하게 Counter 컴포넌트 내에서 increment / decrement 함수를 통해 상태 변화의 로직을 구현하고 있다.

다음은 useReducer 함수를 활용한 카운터이다.

import React, { useReducer } from 'react';

function reducer(state, action) {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1;
    case 'DECREMENT':
      return state - 1;
    default:
      return state;
  }
}

function Counter() {
  const [count, dispatch] = useReducer(reducer, 0);

  const increment = () => {
    dispatch({ type: 'INCREMENT' });
  }

  const decrement = () => {
    dispatch({ type: 'DECREMENT' });
  }

  return (
    <div>
      <h1>{count}</h1>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );
}

가장 먼저 눈에 띄는 것은 reducer 함수가 컴포넌트 외부에 선언되어 있다는 점이다. 해당 함수는 상태 변화의 로직을 담고 있으므로 결국 상태 변화의 로직이 컴포넌트 밖으로 분리되었다고 말할 수 있을 것이다.

오늘의 나는 어떤 어려움이 있었을까?

실습 위주로 공부를 하다보니 중간중간 문득 내가 잘 이해를 하고 있는 건지 단순 타이핑을 하고 있는건지 헷갈릴 때가 있었다. 개념을 어느 정도 이해하고 실습을 진행해야 겠다.

내일의 나는 무엇을 해야할까?

  • Weekly Mission 계획
  • 한크잘 리액트 8, 9장
  • Styled Components 강의 수강
profile
개발자를 지망하는 경영학도

0개의 댓글