// useState 예시
const [number, setNumber] = useState(0)
const onClickHandler = () => {
setNumber(number + 1)
}
리덕스에서는 state 수정이 리듀서에서만 발생함.
컴포넌트에서 직접 값을 바꾸지 않음.
counter.js에 있는 number에 +1을 하고 싶다면
리덕스에서 명령은 action임. 리듀서에게 어떤 동작을 원하는지 전달하는 수단임.
action은 객체 형태로 작성함. 이 객체를 액션 객체라고 부름.
액션 객체는 반드시 type이라는 key를 가져야 함. 리듀서는 type이라는 key를 기준으로 동작을 판단함.
//number에 +1 을 하는 액션 객체
{ type : "PLUS_ONE" };
리덕스 state를 변경하려면 변경 의도마다 액션 객체가 필요함.
액션 객체를 만들었으면 전달해야 함. 이때 사용하는 것이 dispatch.
dispatch는 useDispatch 훅으로 생성.
react-redux에서 import 필요함. 액션 객체를 리듀서로 보내주는 역할을 함.
버튼 클릭 시 액션객체 전달 예시
// 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;
dispatch는 함수임. 그래서 사용할 때 ()를 붙여서 함수를 실행해야 함.
사용 시 ()안에 액션객체를 넣어주면 됨.
“2. 명령(액션 객체) 보내기(dispatch 호출)”에서 리듀서로 액션을 보내긴 했지만 눈으로 확인하고 싶을때. 리듀서에 액션이 잘 들어오는지 확인함.
// 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;
console.log(action) 추가해서
버튼 클릭 시 App.js에서 보낸 액션 객체가 콘솔에 출력되게 함.
dispatch → reducer 전달 구조 확인 가능함.
리듀서가 액션객체를 받아 상태를 바꾸는 원리는 아래와 같음.
“3. 명령(액션 객체) 받기(reducer에서 처리)”에서
“1. 컴포넌트로부터 dispatch를 통해 액션객체를 전달 받음” 까지 구현했으니,
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;
type이 "PLUS_ONE"이면 number가 1 증가한 새로운 state 반환함.
기존 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;
버튼 클릭 시 0 → 1 → 2 로 증가 확인 가능함.
리덕스 state 변경 시 해당 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);
return (
<div>
{number}
<button
onClick={() => {
dispatch({ type: "PLUS_ONE" });
}}
>
+ 1
</button>
{/* ✅️ 빼기 버튼 추가 */}
<button>
- 1
</button>
</div>
);
};
export default App;
// 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);
return (
<div>
{number}
<button
onClick={() => {
dispatch({ type: "PLUS_ONE" });
}}
>
+ 1
</button>
{/* ✅️ dispatch와 액션객체 넣어줌 */}
<button
onClick={() => {
dispatch({ type: "MINUS_ONE" });
}}
>
- 1
</button>
</div>
);
};
export default App;
// src/modules/counter.js
// 초기 상태값
const initialState = {
number: 0,
};
// 리듀서
const counter = (state = initialState, action) => {
// ✅️ 스위치문에 case추가
switch (action.type) {
case "PLUS_ONE":
return {
number: state.number + 1,
};
// action.type이 MINUS_ONE일 때 새로운 state 반환
case "MINUS_ONE":
return {
number: state.number - 1,
};
default:
return state;
}
};
// 모듈파일에서는 리듀서를 export default
export default counter;
액션객체
디스패치
리듀서
useDispatch
useSelector
action type