Redux 2일차

윱니·2023년 11월 9일

1. Redux-Refactoring(action creators, action values)

1. Action Creator 만들기
액션객체를 한 곳에서 관리할 수 있도록 “함수"와 액션 value를 상수로 만듦

// src/redux/modules/counter.js

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

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

리듀서 전체 코드

// src/modules/counter.js

// 추가된 코드 👇 - 액션 value를 상수들로 만들어 줍니다. 보통 이렇게 한곳에 모여있습니다.
const PLUS_ONE = "PLUS_ONE";
const MINUS_ONE = "MINUS_ONE";


// 추가된 코드 👇 - Action Creator를 만들어 줍니다. 
export const plusOne = () => {
  return {
    type: PLUS_ONE,
  };
};

export const minusOne = () => {
  return {
    type: MINUS_ONE,
  };
};


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

// 리듀서
const counter = (state = initialState, action) => {
  switch (action.type) {
    case PLUS_ONE: // case에서도 문자열이 아닌, 위에서 선언한 상수를 넣어줌
      return {
        number: state.number + 1,
      };
    case MINUS_ONE: // case에서도 문자열이 아닌, 위에서 선언한 상수를 넣어줌
      return {
        number: state.number - 1,
      };
    default:
      return state;
  }
};

export default counter;

2. Action Creator 사용하기

  • export된 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;

2. Redux-payload 및 Ducks패턴

Payload란?

  • 지금까지는 ~을이라는 목적어가 없었다면, 이제는 그 목적어가 생긴 것이고 목적어도 액션객체에 담아 같이 보내줌! => payload
// payload가 추가된 액션객체

{type: "ADD_NUMBER", payload: 10} // type뿐만 아니라 payload라는 key와 value를 같이 담음.

payload를 이용해서 기능 구현하기

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

1. app.js에 input구현

// src/App.js


import React from "react";
import { useState } from "react";

const App = () => {
  const [number, setNumber] = useState(0);

  const onChangeHandler = (event) => {
    const { value } = event.target;
		// event.target.value는 문자열
		// 이것을 숫자형으로 형변환해주기 위해서 +를 붙여주기
    setNumber(+value);
  };

	// 콘솔로 onChangeHandler가 잘 연결되었는지 확인
	// input에 값을 넣을 때마다 콘솔에 그 값이 찍히면 연결 성공!
  console.log(number);

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

export default App;

2. counter.js 모듈 작성: Action Creator
작성해야할 것!!

// src/redux/modules/counter.js

// Action Value

// Action Creator

// Initial State

// Reducer

// export default reducer

Action value, Action Creator작성

// src/redux/modules/counter.js

// Action Value
const ADD_NUMBER = "ADD_NUMBER";

// Action Creator
export const addNumber = (payload) => {
  return {
    type: ADD_NUMBER,
    payload: payload, <-key와 value 같으면 payload로 줄여 작성 가능!
  };
};

// Initial State

// Reducer

// export default reducer

3. counter.js 모듈 작성: Initial State, Reducer, 내보내기(export default)
리듀서 로직 작성!
=> Initial State와 리듀서의 기본형태 만들기, 마지막에 export default로 리듀서 내보내기

// src/redux/modules/counter.js

// .. 중략

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

// Reducer 기본형태
const counter = (state = initialState, action) => {
  switch (action.type) {
    default:
      return state;
  }
};

// export default reducer
export default counter;

ADD_NUMBER 로직 구현!
=> 사용자가 컴포넌트에서 Action Creator로 payload를 담아 보내는 것은 액션객체에 담겨지고, 그것은 리듀서에서 action.payload에서 꺼내 사용할 수 있음

// 리듀서

const counter = (state = initialState, action) => {
  switch (action.type) {
    case ADD_NUMBER:
      return {
				// state.number (기존의 nubmer)에 action.paylaod(유저가 더하길 원하는 값)을 더함.
        number: state.number + action.payload,
      };
    default:
      return state;
  }
};

4. 구현된 기능 테스트 하기
(1) App.js에서 useSelector를 이용해 Store의 값을 조회하고 그것을 렌더링하는 기능 추가

// 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;

(2) Action Creator를 import하고, payload를 담아 dispatch

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

// 4. Action Creator를 import 함
import { addNumber } from "./redux/modules/counter";

const App = () => {
	// 1. dispatch를 사용하기 위해 선언해줌
  const dispatch = useDispatch();
  const [number, setNumber] = useState(0);
  const globalNumber = useSelector((state) => state.counter.number);

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

	// 2. 더하기 버튼을 눌렀을 때 실행할 이벤트핸들러를 만들어 줌
  const onClickAddNumberHandler = () => {
		// 5. Action creator를 dispatch 해주고, 그때 Action creator의 인자에 number를 넣어줌.
    dispatch(addNumber(number));
  };

  return (
    <div>
      <div>{globalNumber}</div>
      <input type="number" onChange={onChangeHandler} />
			{/* 3. 더하기 버튼 이벤트핸들러를 연결해줌 */}
      <button onClick={onClickAddNumberHandler}>더하기</button>
      <button>빼기</button>
    </div>
  );
};

export default App;

4. Ducks 패턴

  1. Reducer 함수를 export default 한다.

  2. Action creator 함수들을 export 한다.

  3. Action type은 app/reducer/ACTION_TYPE 형태로 작성한다.

profile
코린이 탈출을 기원하는 코린이

1개의 댓글

comment-user-thumbnail
2023년 11월 9일

:(

답글 달기