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 사용하기
// 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;
Payload란?
~을이라는 목적어가 없었다면, 이제는 그 목적어가 생긴 것이고 목적어도 액션객체에 담아 같이 보내줌! => payload// payload가 추가된 액션객체
{type: "ADD_NUMBER", payload: 10} // type뿐만 아니라 payload라는 key와 value를 같이 담음.
payload를 이용해서 기능 구현하기
- payload를 이용해서 기능 구현 작업 순서
- 사용자가 입력한 값을 받을 input 구현
- Action Creator 작성
- 리듀서 작성
- 구현된 기능 테스트
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;
Reducer 함수를 export default 한다.
Action creator 함수들을 export 한다.
Action type은 app/reducer/ACTION_TYPE 형태로 작성한다.
:(