본격적으로 리덕스를 이용해 카운터 프로그램을 만들기 전, 리덕스의 흐름을 도식화 한 UI 를 살펴보겠습니다.
- View 에서 액션이 일어납니다.
- dispatch 에서 action 이 일어나게 됩니다.
- action 에 의한 reducer 함수가 실행되기 전에 middleware 가 작동합니다.
- middleware 에서 명령내린 일을 수행하고 난 뒤, reducer 함수를 실행합니다.
- reducer 의 실행결과, store 에 새로운 값을 저장합니다.
- store 의 state 에 subscribe 하고 있던 UI 에 변경된 값을 줍니다.
counter.js 모듈의 state 수정 기능 만들기(+1 기능 구현해보기)
counter.js 모듈에 있는 state 의 값이 변경되는 과정
useState() 를 사용해서 number 에 +1 을 할 때는 setNumber 를 이용해서 +1 을 해주었습니다.
리덕스에서의 값의 수정은 리듀서에서 일어난다고 앞에서 배웠습니다. 만약 counter.js 모듈에 있는 number 에 +1을 하고 싶다면, 다음 순서대로 진행합니다.
- 리듀서에게 보낼 number 를 +1 하라는 "명령"(action 객체) 을 만듭니다.
- 명령을 보냅니다.
- 리듀서에서 명령을 받아 number+1 을 수행합니다.
1. 리듀서에게 보낼 "명령"(type) 만들기
리듀서에게 number 를 +1 을 하라고 명령을 보내야 합니다. 명령을 보내기 전에 '명령' 을 만들어야 합니다. 리덕스에서는 그 명령을 Action 이라고 합니다. 즉, 리듀서에게 내가 어떤 Action 을 하길 원한다. 라고 표현하는 것이죠. 행동을 코드로 나타내면 객체로 만듭니다. 그래서 이것을 액션 객체라고 합니다.
액션 객체는 반드시 type 이라는 key 를 가져야 합니다. 왜냐하면 액션 객체를 리듀서에게 보냈을 때 리듀서는 객체 안에서 type 이라는 key 를 보기 때문입니다.
// 예시 코드
//number에 +1 을 하는 액션 객체
{ type : "PLUS_ONE" };
2. useDispatch : "명령"(액션 객체) 보내기
명령을 만든 후, 리듀서에게 명령을 보내야 합니다. 조금 더 정확하게 표현하기 위해 지금부터는 '명령'이 아닌 '액션객체' 라고 표현하겠습니다.
액션객체를 리듀서로 보내기 위해서는 새로운 훅을 사용해야 합니다. 그 훅은 useDispatch 라는 훅입니다. react-redux 에서 import 해서 사용할 수 있으며, 만든 액션 객체를 리듀서로 보내주는 역할을 하는 훅입니다.
useDispatch 라는 훅을 사용하기 위해서는 컴포넌트 안에서 아래와 같이 먼저 코드를 작성해서 dispatch 라는 변수를 생성해줘야 합니다. 이렇게 생성한 dispatch 는 '함수' 라는 점을 기억해야 합니다. 그래서 dispatch 를 사용할 때 () 를 붙여서 함수를 실행하게 됩니다.
// src/App.js
import React from "react";
import { useDispatch } from "react-redux"; // import 해주세요.
const App = () => {
const dispatch = useDispatch(); // dispatch 생성
return (
<div>
<button>+ 1</button> {/* 버튼을 하나 추가해주세요. */}
</div>
);
};
export default App;
그리고 dispatch 를 사용할 때 ( ) 안에 액션 객체를 넣어주면 됩니다. 만약 어떤 버튼을 클릭했을 때 리듀서로 액션객체를 보내고 싶다면 아래와 같이 코드를 작성합니다.
// src/App.js
import React from "react";
import { useDispatch } from "react-redux"; // import 해주세요.
const App = () => {
const dispatch = useDispatch(); // dispatch 생성
return (
<div>
<button
onClick={() => { // 이벤트 핸들러 추가
dispatch({ type: "PLUS_ONE" }); // 마우스를 클릭했을 때 dispatch가 실행되고, ()안에 있는 액션객체가 리듀서로 전달됩니다.
}}
>
+ 1
</button>
</div>
);
};
export default App;
이렇게 해서 dispatch 를 이용해 액션객체를 리듀서로 보낼 수 있습니다.
3. 액션 객체 받기
리듀서로 액션객체를 보냈으니, 리듀서에서 액션객체가 잘 왔는지 확인해보겠습니다.
아마 현재 counter.js 모듈의 코드가 이런 상태일 것입니다. 코드를 수정해볼 것인데요. App.js 에서 보낸 액션객체를 받을 수 있도록 구현해볼 것입니다.
// src/redux/modules/counter.js
// 초기 상태값
const initialState = {
number: 0,
};
// 리듀서
const counter = (state = initialState, action) => {
switch (action.type) {
default:
return state;
}
};
// 모듈파일에서는 리듀서를 export default 한다.
export default counter;
리듀서에 action 을 콘솔로 찍어보겠습니다.
// src/redux/modules/counter.js
// 초기 상태값
const initialState = {
number: 0,
};
// 리듀서
const counter = (state = initialState, action) => {
console.log(action); // 여기에 console.log(action) 추가
switch (action.type) {
default:
return state;
}
};
// 모듈파일에서는 리듀서를 export default 한다.
export default counter;
그리고 다시, App.js 로 돌아가서 버튼을 눌러서 버튼을 클릭해볼까요? counter.js 에서 콘솔로 찍은 action 이 보이는 것을 확인할 수 있습니다. 리듀서에 있는 action 은 App.js 에서 dispatch 로 보낸 그 액션객체임을 알 수 있습니다.
이렇게 해서, App.js 에서 dispatch 를 통해서 보낸 액션객체가 리듀서로 잘 들어가고 있음을 확인할 수 있습니다.
4. 액션객체 명령대로 리듀서가 state 값을 변경하는 코드 구현하기
이제 액션객체를 잘 보내고, 잘 받고 있음을 확인했으니 state에 있는 number 를 실제로 변경하는 로직 코드를 구현해보겠습니다. 로직코드는 리듀서 안에 있는 switch 문으로 작성됩니다.
리듀서가 액션객체를 받아 상태를 바꾸는 원리는 아래와 같습니다.
- 컴포넌트로부터 dispatch 를 통해 액션객체를 전달받습니다.
- action 안에 있는 type 을 switch 문을 통해 하나씩 검사해서, 일치하는 case 를 찾습니다.
- type 과 case 가 일치하는 경우에, 해당 코드가 실행되고 새로운 state 를 반환(return) 합니다.
- 리듀서가 새로운 state 를 반환하면, 해당 state 가 새로운 모듈의 state 가 됩니다.
바로 이전 단계에서 1번까지 구현했으니, 2~4번을 한 번 직접 코드로 작성해보겠습니다.
// src/modules/counter.js
// 초기 상태값
const initialState = {
number: 0,
};
// 리듀서
const counter = (state = initialState, action) => {
console.log(action);
switch (action.type) {
// PLUS_ONE이라는 case를 추가한다.
// 여기서 말하는 case란, action.type을 의미한다.
// dispatch로부터 전달받은 action의 type이 "PLUS_ONE" 일 때
// 아래 return 절이 실행된다.
case "PLUS_ONE":
return {
// 기존 state에 있던 number에 +1을 더한다.
number: state.number + 1,
};
default:
return state;
}
};
// 모듈파일에서는 리듀서를 export default 한다.
export default counter;
action 이 {type: "PLUS_ONE"} 이기 때문에 리듀서 안에 있는 switch 문은 action.type 을 조회합니다. 그리고 일치하면, return 절이 실행되고 새로운 state 를 반환합니다.
dispatch 를 통해 액션객체를 App.js 컴포넌트에서 리듀서로 보냈고, 리듀서에서 받아 switch 문을 통해 조건을 찾았고, 그에 해당했을 때 state 값을 변경하는 로직까지 모두 구현했습니다.
정리
- 액션객체란, 반드시 type이란 key를 가져야 하는 객체이다. 또한 리듀서로 보낼 “명령"이다.
- 디스패치란, 액션객체를 리듀서로 보내는 “전달자” 함수이다.
- 리듀서란, 디스패치를 통해 전달받은 액션객체를 검사하고, 조건이 일치했을 때 새로운 상태값을 만들어내는 “변화를 만들어내는" 함수이다.
- 디스패치(dispatch)를 사용하기위해서는 useDispatch() 라는 훅을 이용해야 한다.
- 디스패치는 스토어의 내장함수 중 하나입니다.
- 우선, 디스패치는 액션을 발생 시키는 것 정도로 이해하시면 됩니다.
- dispatch 라는 함수에는 액션을 파라미터로 전달합니다.. dispatch(action) 이런식으로 말이죠.
- 액션객체 type의 value는 대문자로 작성한다. (JS에서 상수는 대문자로 작성하는 룰이 있음)
'항해 16기 > Today I Learned' 카테고리의 다른 글
[항해 22일차] TIL_React 숙련주차 : Redux-Refactoring(action creators, action values) (0) | 2023.09.04 |
---|---|
[항해 24일차] TIL_React 숙련주차 : Redux - Payload 및 Ducks 패턴 (0) | 2023.08.30 |
[항해 19일차] TIL_React 숙련주차 : Redux 설정 + 카운터 프로그램 만들기 (0) | 2023.08.30 |
[항해 18일차] TIL_React 숙련주차 : Redux 란? (0) | 2023.08.30 |
[항해 17일차] TIL_React 숙련주차 : Redux 설정 (0) | 2023.08.30 |