본문 바로가기

리액트 공식 문서 읽기

20화: Extracting state logic into a reducer

이 글은 단순히 리액트 공식 문서를 읽고 베꼈을 뿐이다!! 학습 목적이라면 공식 문서를 보는 걸 추천한다.

 

참새. Unsplash 에 Tomislav Galić 님이 올림

공식 문서

https://react.dev/learn/extracting-state-logic-into-a-reducer

 

Extracting State Logic into a Reducer – React

The library for web and native user interfaces

react.dev

reducer로 로직을 통합하기

  • 컴포넌트가 점점 더 복잡해지면 컴포넌트의 상태 업데이트 로직들을 한눈에 보기 힘들어짐
  • reducer를 이용하면 이런 로직들을 접근이 쉬운 하나의 외부 함수로 만들 수 있음

useState에서 useReducer로 옮기는 세 단계

1. 상태 설정에서 행동(action) 보내기로 바꾸기

  • 모든 상태 설정 로직을 지우기
  • 대신 '어떤 행동을 했길래' 상태가 설정되어야 하는지 생각하기
  • 그리고 dispatch() 함수의 인자에 어떤 일이 일어났는지 알려줄 수 있는 최소한의 정보들을 같이 담기
  • 이 정보들을 action object라고 함
  • action object의 형태에는 제약이 없음: 컨벤션으로 행동의 이름을 type으로 주는 경우가 일반적
const addNewTask = (text) => {
  dispatch({
    type: 'added',
    text,
  });
}

2. reducer 함수 만들기

  • 상태 관련 로직들을 넣는 곳
  • 인자로 두 개를 받음: 현재 상태, action object
  • 반환값은 하나: 다음 상태
  • 인자로 상태를 받기 때문에 컴포넌트 밖에 정의 가능
  • if/else 또는 switch-case를 통해 action type별로 나누어 진행
  • 이름이 'reducer'인 이유: 배열의 reduce() 메서드와 같은 작동 원리임━이전 상태와 현재 값을 받아서 다음 상태를 반환

3. 컴포넌트에서 reducer 쓰기

  1. import { useReducer } from 'react';
  2. useState 가 있는 부분을 const [myState, dispatch] = useReducer(myStateReducer, myInitialState); 이렇게 바꾸기
  • 이런 방식으로 컴포넌트 로직의 관심사 분리 가능
  • 이벤트 핸들러들이 '무엇이 일어났는지'만 알면 되고 '어떻게 상태를 바꿔야 하는지'는 몰라도 되게 할 수 있음

useState vs useReducer

  • 코드 길이
    • 일반적으로 useState가 더 짧음
    • 많은 이벤트 핸들러들이 상태 변경에 같은 로직을 사용하는 경우 useReducer로 코드 길이를 줄일 수 있음
  • 가독성
    • useState는 상태 업데이트가 간단할 때는 보기 편한데 복잡해질수록 어려움
    • useReducer는 행동과 로직을 분리하여 이벤트 핸들러에선 행동만 볼 수 있어서 좋음
  • 디버깅
    • useState를 쓸 경우 어디에서, 왜 상태 변경 버그가 났는지 찾기 어려울 수 있음
    • useReducer는 상태 변경 로직이 한 군데에 있고, action type 때문에 범인 찾기가 상대적으로 쉬움
  • 테스팅
    • reducer 함수는 컴포넌트에 의존하지 않는 순수함수이기 때문에 테스트가 가능함
  • 개인 취향

reducer 잘 만들기

  • reducer는 순수해야 함
  • 각 action은 하나의 사용자 상호작용만을 나타내야 함 (설령 그 행동이 여러 개의 데이터를 바꾸더라도)