리덕스의 흐름 도식화
- View 에서 액션이 일어난다.
- dispatch 에서 action이 일어나게 된다.
- action에 의한 reducer 함수가 실행되기 전에 middleware가 작동한다.
- middleware 에서 명령내린 일을 수행하고 난뒤, reducer 함수를 실행한다. (3, 4번은 아직 몰라도 됩니다!)
- reducer 의 실행결과 store에 새로운 값을 저장한다.
- store의 state에 subscribe 하고 있던 UI에 변경된 값을 준다.
출처 : https://velog.io/@annahyr/리덕스-흐름-이해하기
1. counter.js 모듈의 state 수정 기능 만들기 (+ 1 기능 구현해보기)
(1) 어떻게 counter.js 모듈에 있는 state의 값을 변경할 수 있을까?
useState()를 사용해서 number에 +1을 할 때는 setNumber을 이용해서 +1을 해주었다.
// 예시 코드
// local state
const [number, setNumber] = useState(0)
// click handler
const onClickHandler = () => {
setNumber(number + 1)
}
리덕스에서는 값의 수정이 리듀서에서 일어난다.
따라서 값을 수정하려면 다음의 과정을 거쳐야 한다.
- 리듀서에게 보낼 number를 +1 하라는 “명령”을 만든다.
- 명령을 보낸다.
- 리듀서에서 명령을 받아 number +1을 한다.
(2) 리듀서에게 보낼 '명령' 만들기
리덕스에서는 명령을 Action 이라고 하며, 리듀서에게 '내가 어떤 Action을 하길 원한다'라고 표현한다.
Action은 객체로 만들기 때문에 이것을 액션 객체라고 부른다..
액션 객체는 반드시 type이라는 key를 가져야 한다.
우리가 이 액션 객체를 리듀서에게 보냈을 때 리듀서는 객체 안에서 type이라는 key를 보기 때문이다.
// 예시 코드
//number에 +1 을 하는 액션 객체
{ type : "PLUS_ONE" };
리덕스 모듈에 있는 state을 변경하기 위해서는 그에 해당하는 액션 객체를 모두 만들어줘야 한다.
(3) "명령"(액션 객체) 보내기
액션객체를 보내기 리듀서로 보내기 위해서는 useDispatch라는 훅을 사용해야 한다.
// 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가 실행되고, ()안에 있는 액션객체가 리듀서로 전달된다.
dispatch({ type: "PLUS_ONE" });
}}
>
+ 1
</button>
</div>
);
};
export default App;
(4) 액션 객체 받기
리듀서에 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;
액션객체가 리듀서로 잘 들어가고 있음을 눈으로 직접 확인할 수 있다.
(5) 액션객체 명령대로 리듀서가 state값을 변경하는 코드 구현하기
- 컴포넌트로부터 dispatch를 통해 액션객체를 전달 받는다.
- action 안에 있는 type을 스위치문을 통해 하나씩 검사해서, 일치하는 case를 찾는다.
- type과 case가 일치하는 경우에, 해당 코드가 실행되고 새로운 state를 반환(return) 한다.
- 리듀서가 새로운 state를 반환하면, 그게 새로운 모듈의 state가 된다.
// 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;
(6) useSelector로 변경된 state값 확인하기
// src/App.js
import React from "react";
import { useDispatch, useSelector } from "react-redux";
const App = () => {
const dispatch = useDispatch();
// 👇 코드 추가
const number = useSelector((state) => state.counter.number);
console.log(number); // 콘솔 추가
return (
<div>
{/* 👇 코드 추가 */}
{number}
<button
onClick={() => {
dispatch({ type: "PLUS_ONE" });
}}
>
+ 1
</button>
</div>
);
};
export default App;
정리
- 액션객체란, 반드시 type이란 key를 가져야 하는 객체이다. 또한 리듀서로 보낼 “명령"이다.
- 디스패치란, 액션객체를 리듀서로 보내는 “전달자” 함수이다.
- 리듀서란, 디스패치를 통해 전달받은 액션객체를 검사하고, 조건이 일치했을 때 새로운 상태값을 만들어내는 “변화를 만들어내는" 함수이다.
- 디스패치(dispatch)를 사용하기위해서는 useDispatch() 라는 훅을 이용해야 한다.
- 디스패치는 스토어의 내장함수 중 하나이다.
- 디스패치는 액션을 발생 시키는 것 정도로 이해하면 된다.
- dispatch 라는 함수에는 액션을 파라미터로 전달한다. dispatch(action)
- 액션객체 type의 value는 대문자로 작성한다. (JS에서 상수는 대문자로 작성하는 룰이 있음)
'웹개발 > react' 카테고리의 다른 글
[React] Redux - Payload 및 Ducks 패턴 (0) | 2024.02.03 |
---|---|
[React] Redux Refactoring(action creators, action values) (1) | 2024.02.01 |
[React] useRef란? useState와의 차이 (0) | 2024.01.31 |
[React] Redux + 설정 카운터 프로그램 만들기 (1) | 2024.01.29 |
[React] 리덕스(Redux)란 무엇인가? (1) | 2024.01.27 |