Redux ducks pattern (action types , action creators...)

soo's·2023년 4월 17일
0

TIL

목록 보기
41/53
post-thumbnail

0. ducks pattern

redux를 사용할 때
예를 들어, counter에 관한 모듈인 counter.js 가 있다면
그 안에는 초기 상태값과 reducer 함수가 있고, reducer 함수에는 어떤 action.type에 따른 값을 반환할지 명시되어있을 것이다.

그런데 이 부분에서 action.type을 일일이 손으로 하드코딩하다보면 humon error가 발생할 수 있고, 혹은 프로젝트 컨벤션이 수정되어 type을 기존의 'type'에서 앞에 모듈을 명시해주려고, '모듈/type' 이렇게 변경해야 할 수도 있다.

만약 하드코딩된 type들을 모두 변경해야 한다면 정말 눈 앞이 깜깜할 것이다. 따라서 우리는 Redux를 사용함에 있어서 그 에러를 줄이고 생산성을 높여줄 수 있는 action value와 action creators를 사용해야 한다.

이런 문맥에서 나온 것이 바로 ducks pattern이다.
리덕스의 덕스 패턴(Ducks pattern)은 리덕스 애플리케이션에서 모듈성을 촉진하고 코드를 구성하는 방법을 제안하는 디자인 패턴. 덕스 패턴은 action value, reducer 및 action creator를 하나의 파일에 캡슐화하여 관련 코드를 그룹화합니다.

덕스 패턴을 구현하려면, 다음과 같은 구조를 따르는 모듈 파일을 작성합니다.

  1. 액션 타입(action types) 정의
  2. 액션 생성자(action creators) 함수 정의
  3. 초기 상태(initial state) 객체 정의
  4. 리듀서(reducer) 함수 정의

이러한 코드를 하나의 파일에 캡슐화하면, 코드의 의도를 파악하기 쉬워지며, 애플리케이션 전체에서 코드를 재사용할 수 있음. 또한, 덕스 패턴을 따르면 리덕스의 combineReducers 함수를 사용하여 애플리케이션의 상태를 쉽게 결합할 수 있음

1. Actioin types

action types를 작성할 때는
app/reducer/action type 형식으로 작성하는 것이 좋다.
아래 예시를 봐보자.

// counter.js
// 초기 상태값
const initialState = {
  number: 0,
};

// reducer 함수 - anction 객체를 받아서 그 type에 따라 state 변경시키는 함수
const counter = (state = initialState, action) => {
  switch (action.type) {
    case "plus":
      return { ...state, number: state.number + 1 };
    case "minus":
      return { ...state, number: state.number - 1 };
    default:
      return state;
  }
};
export default counter;

기존 코드는 위와 같다.
보시다싶이 action.type을 문자열로 입력해서 사용하고 있다. 이 부분을 action value로 변수에 담아 사용한다면 아래와 같다.

// action types
export const PLUS = "app/reducer/PLUS";
export const MINUS = "app/reducer/MINUS";

// 초기 상태값
const initialState = {
  number: 0,
};

// reducer 함수 - anction 객체를 받아서 그 type에 따라 state 변경시키는 함수
const counter = (state = initialState, action) => {
  switch (action.type) {
    case PLUS:
      return { ...state, number: state.number + 1 };
    case MINUS:
      return { ...state, number: state.number - 1 };
    default:
      return state;
  }
};
export default counter;

이렇게 바꿔서 하드코딩을 없애줄 수 있음

action creators

// counter.js
... 생략
// action creators
export const plus_one = () => {
  return { type: PLUS };
};
export const minus_one = () => {
  return { type: MINUS };
};
... 생략

얘네 다 export 해주는 이유?
컴포넌트에서 dispatch에 action 객체 입력할 때 휴먼에러 발생하지 말라고 action creators 사용하는거니까
컴포넌트에서도 쓸 수 있게 export 해주는거임!

사용하기

마지막으로 내가 사용할 App.js에서 얘네를 import 해와서 아래와 같이 작성하면 됨

// App.js
import React from "react";
import { useDispatch, useSelector } from "react-redux";
import { plus_one, minus_one } from "./redux/modules/counter"; // import 잊지말기!

const App = () => {
  const counterStore = useSelector((state) => state.counter);
  const dispatch = useDispatch();
  const handleClickPlus = () => {
    dispatch(plus_one());
  };
  const handleClickMinus = () => {
    dispatch(minus_one());
  };
  return (
    <>
      <div>현재 넘버 : {counterStore.number}</div>
      <button onClick={handleClickPlus}>+</button>
      <button onClick={handleClickMinus}>-</button>
    </>
  );
};

export default App;

핵심은 plus_one, minus_one 둘 다 객체를 리턴하는 함수이기 때문에 dispatch안에 저렇게 함수형태로 넣어주면 된다.
그러면 하드코딩 bye~

0개의 댓글