💻 JavaScript/기초 문법

ReactJS 숙련: action creators, action values, payload, Ducks 패턴

seheej 2024. 8. 26. 20:15
01. Action Creator

1-1. Action Creator란?

  • Action Creator는 Redux에서 액션 객체를 생성하는 함수
  • Redux에서 액션 객체를 하드코딩으로 작성하는 대신, 이를 함수로 만들어 사용함으로써 코드의 유지보수성을 높이고, 오타를 방지할 수 있음
  • 특히 프로젝트 규모가 커질수록 액션 타입의 변경이 빈번하게 일어날 수 있는데, Action Creator를 사용하면 이러한 변경을 중앙에서 쉽게 관리할 수 있음

1-2. Action Creator 만들기

  • 액션 value를 상수로 선언하고, 해당 상수를 이용해 액션 객체를 반환하는 함수를 만듦
  • 리듀서와 컴포넌트에서 이 Action Creator를 사용해 코드의 유지보수성을 높임
// src/redux/modules/counter.js

const PLUS_ONE = "PLUS_ONE"; // value는 상수로 생성

// 액션객체를 반환하는 함수 생성
// export 가 붙는 이유는 plusOne()는 밖으로 나가서 사용될 예정이기 때문입니다.
export const plusOne = () => { 
  return {
    type: PLUS_ONE, // type에는 위에서 만든 상수로 사용 (vscode에서 자동완성 지원)
  };
};

 

1-3. Action Creator 사용하기

 

  • Action Creator를 import함
  • dispatch에 Action Creator를 넣어줌 이렇게 하면 코드 수정이 쉬워짐
// src/App.js

import React from "react";
import { useDispatch, useSelector } from "react-redux";

// 사용할 Action creator를 import 합니다.
import { minusOne, plusOne } from "./redux/modules/counter";

const App = () => {
  const dispatch = useDispatch();
  const number = useSelector((state) => state.counter.number);

  return (
    <div>
      {number}
      <button
        onClick={() => {
          dispatch(plusOne()); // 액션객체를 Action creator로 변경합니다.
        }}
      >
        + 1
      </button>
      {/* 빼기 버튼 추가 */}
      <button
        onClick={() => {
          dispatch(minusOne()); // 액션객체를 Action creator로 변경합니다.
        }}
      >
        - 1
      </button>
    </div>
  );
};

export default App;

 

1-4. 왜 Action Creator를 사용해야 하나?

  1. 휴먼에러 방지: 자동완성을 통해 오타를 방지할 수 있음
  2. 유지보수의 효율성 증가: 한 번의 수정으로 여러 군데에서 수정된 효과를 얻을 수 있음
  3. 코드 가독성: Action Creator가 정리되어 있으면, 모듈이 가지고 있는 모든 액션을 한눈에 파악할 수 있음

 

02. payload

 

2-1. Payload란?

payload는 액션 객체에 데이터를 담아 리듀서로 보내는 것임 예를 들어, 특정 숫자를 더하거나 빼고 싶을 때 그 값을 함께 전달함

2-2. payload를 이용한 기능 구현 작업 순서

  1. 사용자가 입력한 값을 받을 input 구현
  2. Action Creator 작성
  3. 리듀서 작성
  4. 구현된 기능 테스트

1. input 구현

// src/App.js

import React from "react";

const App = () => {
  return (
    <div>
      <input type="number" />
      <button>더하기</button>
      <button>빼기</button>
    </div>
  );
};

export default App;

 

2. Action Creator 작성

// src/redux/modules/counter.js

// Action Value
const ADD_NUMBER = "ADD_NUMBER";
const SUBSTRACT_NUMBER = "SUBSTRACT_NUMBER";

// Action Creator
export const addNumber = (payload) => {
  return {
    type: ADD_NUMBER,
    payload: payload,
  };
};

export const substractNumber = (payload) => {
  return {
    type: SUBSTRACT_NUMBER,
    payload, // 축약형
  };
};

// Initial State

// Reducer

// export default reducer

3. Reducer 작성 (Initial State와 리듀서의 기본 형태)

// src/redux/modules/counter.js

// .. 중략

// Initial State
const initialState = {
  number: 0,
};

// Reducer 기본형태
const counter = (state = initialState, action) => {
  switch (action.type) {
    case ADD_NUMBER:
      return {
        number: state.number + action.payload,
      };
    case SUBSTRACT_NUMBER:
      return {
        number: state.number - action.payload,
      };
    default:
      return state;
  }
};

// export default reducer
export default counter;

4. 구현된 기능 테스트

// src/App.js

import React from "react";
import { useState } from "react";
import { useSelector } from "react-redux";

const App = () => {
 	const [number, setNumber] = useState(0);
	// 1. 아래 코드 추가 👇
	const globalNumber = useSelector((state) => state.counter.number);

    const onChangeHandler = (event) => {
		const { value } = event.target;
		setNumber(+value);
	};

  return (
    <div>
		{/* 2. 아래 코드 추가  */}
		<div>{globalNumber}</div>
		<input type="number" onChange={onChangeHandler} />
		<button>더하기</button>
		<button>빼기</button>
    </div>
  );
};

export default App;