React - Redux

김형석·2022년 7월 1일
0

WECODE

목록 보기
32/33

Redux란

Redux는 자바스크립트 앱을 위한 예측 가능한 상태 컨테이너이다.
그럼 언제 사용하는 것이 좋을까?? 기본적으로 react의 기능만으로 대응하기 힘들 정도로 애플리케이션의 상태 관리가 복잡해졌다고 확실히 판단이 되었을 때 사용하는 것이 좋다.

Redux Concepts

Draw by 승현 손

1. View

유저가 사용하는 화면, 버튼, react 컴포넌트 등의 UI 구성 요소

2. Action / Action Creator

  • Action 이란 상태 변화에 대한 의도를 표현하는 단순한 자바스크립트 객체
  • Action Creator는 이러한 Action 객체를 정해진 틀에 맞게 리턴하는 단순한 함수, Action을 reducer로 보내는 역할을 하는 건 아니다.
export const addCart = (item) => { // 액션 "생성 함수"
  return {
    type: "ADD_ITEM", // 액션 "객체"
    payload: item,
  };
};
  • Action은 Store에 담긴 데이터를 변형시킬 수 있는 유일한 방법
    store.dispatch 함수의 인자로 담겨 reducer에 어떻게 store를 변경시킬 것인지에 대한 정보를 제공 하는 역할
  • 필수적인 type 프로퍼티를 제외하면, 사용자의 필요에 따라 추가 가능
const ADD_TODO = {
  type: "ADD_TODO",
  payload: { content: "출근하기", priority: 1 }
}

3. Dispatcher

  • Action 객체를 Reducer에 보내는 역할을 하는 함수. store.dispatch()형태로 제공
  • 기본 dispatch함수는 반드시 동기적으로 처리되어야 함.
  • 만약 비동기 Actio이 필요하다면 비동기 처리가 완료된 이후에 Action 을 Dispatch 하거나, 미들웨이(Action이 Reducer로 들어 가기 전에 거쳐가는 곳)를 활용해 비동기 처리를 해줘야 함

Reducer

  • reducer는 (preciousState,action) => newState 의 형태를 가지고, 순수함수이며 예측 가능해야 한다.
  • reducer는 업데이트 되기 이전의 state를 기반으로 새로 받은 action에 미리 준비된 로직을 처리해 새로운 store를 리턴하는 함수이다. 즉, reducer는 감지된 action 타입에 따라 이벤트를 처리하는 이벤트 리스너로도 생각할 수 있다.
// Array.prototye.reduce()
const cart = [
  { id: 1, name: "청바지", price: 10000, quantity: 2 },
  { id: 2, name: "반바지", price: 10000, quantity: 1 },
  { id: 3, name: "반팔", price: 10000, quantity: 2 },
];

const totalPrice = cart.reduce((acc, cur) => {
  return acc + cur.price * cur.quantity
}, 0);

redux의 Reducer 역시 Store와 Action을 받아 새로운 Store로 값을 합쳐 내보낸다

const INITIAL_STATE = [];

// redux/cart.js
export default function cartReducer(state = INITIAL_STATE, action) {
  switch (action.type) {
    case "ADD_ITEM":
      return [...state, action.payload]; // 이전 상태에 새로운 item을 추가
    case "DELETE_ITEM":
      return state.filter((product) => product.id !== payload.id);
    default:
      return state; // 해당 사항 없으면 이전 상태를 그대로 리턴
  }
}

// redux/index.js
import { combineReducers } from "redux";
import cartReducer from "./cartReducer";

export default combineReducers({ cartReducer });
  • reducer는 다음과 같은 요소로 구분된다.
  1. Root Reducer: 실제로 createStore의 첫 번째 인자로 전달되는 함수로, 유일하게 (state, action)=>newState 형태의 로직을 가져야 한다.
  2. Slice Reducer: 상태 트리의 일부분만을 업데이트하는 리듀서이다. 여러 Slice Reducer들이 결합되어 Root Reducer를 구성하게 된다.

Store

스토어의 쌩얼

  • Redux 앱 전체의 상태로 보통 깊게 중첩되어 있는 객체
  • store에서 관리되고, store.getState()로 읽어올 수 있음
  • 항상 직렬화(Serialization) 가능해야 하기 때문에 JSON으로 쉽게 변환할 수 없는 것들은 제외하는게 좋다(ex. 함수, Promise 등)

Middleware

  • 비동기 API 호출 등 순수하지 않은 요청(Side Effect)을 처리하거나, Redux Store로 전달되는 Action 등을 로깅하는 장소이며 Reducer가 액션을 처리하기 전에 실행되는 함수
  • Middleware를 설정하지 않으면 dispatch한 액션은 곧바로 리듀서로 보내짐
  • 대표적인 Middleware로 redux-logger, redux-thunk, redux-saga 등이 있음
// redux-thunk
export default function thunkMiddleware({ dispatch, getState }) {
  return next => action =>
    typeof action === 'function' ?
      action(dispatch, getState) :
      next(action);
}

출처 westudy

profile
블로그 이사 : https://hengxi.tistory.com

0개의 댓글