리덕스
store,action,reducer
store는 상태가 관리되는 오직 하나의 공간 컴포넌트와 별개로 store라는 공간이 있어서 필요한
상태값을 담아준다
컴포넌트에서 전역으로 상태값이 필요할 때 store에 접근해서 데이터를 가져온다.
액션은 store에 전달할 데이터를 자칭 액션을 사용해서 스토어에 데이터를 보내게 된다.
액션은 자바스크립트 객체 형식으로 만들어져 있음. dispatch함수를 사용해서 매개변수로
액션을 전달하면 리듀서가 호출되면서 매개변수로 액션을 받게되고
dispatch(액션)=> 리듀서가 호출되면서 리듀서에 액션을 전달하게 된다.
reducer=>dispatch 함수를 통해 액션을 reducer 함수에 전달한다.
reducer함수는 매개변수로 전달받은 액션이 뭔지 보고 스토어에 상태를 업데이트 할지 여부를 결정
리덕스란
리액트에서 사용할 수 있는 하나의 라이브러리
리액트는 자식 컴포넌트에 props로 전달받은 값을 사용하는데
다른 컴포넌트와 데이터 공유를 직접하기 불가능 하다.
그래서 공유해야할 데이터를 공유받은 자식 컴포넌트들이 사용할 때 공통적 부모 store를 만들어서
데이터를 공유 할 수 있도록 만들어 준것 . 리액트의 데이터 흐름은 단방향이라 이런 단점을 보완하기 위해
만들었다.
사용하면 좋지만 사람들이 좀 어려워 함
쉽게 말해서 데이터를 직접 부모한테 전달 받는게 아니라 컴포넌트의 값을 요청하고 전달하는걸 직접 할 수 있다.
스토어에 있는 데이터를 변수에 값을 넣는 것처럼 바로 바꿀순 없고 함수를 사용해서 값을 전달할 수 있다.
리덕스의 동작 구조
컴포넌트=>useDispatch=>Action=>Reducer->store
컴포넌트가 Action을 보내고 Reducer가 전달 받고 값을 업데이트할지 여부를 체크한뒤 store의 값을 최신화 시켜준다.
Action은 동작할 기능 이름 행동
Reducer는 함수를 실행해서 내가 동작할 기능을 조건문으로 작성해둔 파일(메뉴판)
컴포넌트가 어떤 Action을 실행시킬지 Reducer함수로 받고 store의 값을 최신화 시켜준다.
store의 값이 바뀌면 전역 상태를 가져오고 있는 컴포넌트들을 리랜더링된다.
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { Provider } from "react-redux";
import store from "./redux/store";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
// Provider 컴포넌트는 자식 컴포넌트에 store를 주입해준다.
<Provider store={store}>
<App />
</Provider>
);
2.redux는 기본적으로 action이 reducer의 매개변수로 들어가 store가 변하는 방식으로 작동된다.
action을 실행시키는 곳을 정할 때는useDispatch를 쓴다.
import React from "react";
import { useDispatch } from "react-redux";
// 전역 상태에 있는 값을 업데이트 해줄 것이다.
// useDispatch 액션을 보낼 수 있게 react hook 함수를 사용하자.
const Count = () => {
// useDispatch
const dispatch = useDispatch();
// dispatch 함수를 사용해서 action을 던질 수 있다.
// dispatch 함수를 사용할 때 매개변수로 객체를 전달 해주자
// 객체의 규칙 {type,payload}
// type: 동작시킬 행동의 이름
// payload: 선택사항, 있어도되고 없어도 됨. 상태를 변경할 때 데이터 전달이 필요할 경우 사용
const handlerAdd = () => {
dispatch({ type: "sushi" });
};
const handlerRemove = () => {
dispatch({ type: "ramen" });
};
return (
<div>
<button onClick={handlerAdd}>초밥</button>
<button onClick={handlerRemove}>라멘</button>
</div>
);
};
export default Count;
3.만약 전해줄 데이터가 있다면 payload를 활용하자
import React, { useEffect } from "react";
import { useDispatch } from "react-redux";
const Count2 = () => {
// useDispatch
const dispatch = useDispatch();
// 상태 패턴 관리할 땐 대문자로 쓰자
const handlerAdd = () => {
dispatch({ type: "LOGIN", payload: true });
};
const handlerRemove = () => {
dispatch({ type: "LOGOUT", payload: false });
};
return (
<div>
<button onClick={handlerAdd}>로그인</button>
<button onClick={handlerRemove}>로그아웃</button>
</div>
);
};
export default Count2;
4.dispatch로 전했다면 reducer에서 받아야만 한다.
reducer.js
// 리듀서 함수
// 메뉴판
// 초기상태가 필요한데
// 카운트 값 하나
let init = {
count: 0,
isLogin: false,
userState: {
userId: "",
userAge: 0,
},
};
// 주문 받으면 action(음식 이름)
// 전역 상태를 개발하면서 브라우저의 개발자 모드로 전역상태가 바뀌는걸 실시간으로 확인하고 싶음
// npm install redux-devtools-extension
function reducer(state = init, action) {
console.log(action);
// 음식이 뭔지 조건문
switch (action.type) {
case "sushi":
// 리듀서 함수의 반환값으로 저장소를 최신화 시켜준다.
// 저장소는 대기하다가 리듀서가 호출되면 값을 반환받아서 최신화 시켜줌
// 리듀서에서 반환된 값을 비교하는게 아니라 주소를 비교하기 때문에
// 값이 변해도 모름 주소가 바뀌지 않으면 업데이트가 되지 않는다.
return { ...state, count: state.count + 1 };
case "ramen":
return { ...state, count: state.count - 1 };
case "LOGIN":
// ...state원본 객체의 값을 복사
return { ...state, isLogin: action.payload };
case "LOGOUT":
return { ...state, isLogin: action.payload };
default:
// 반환값이 무조건 있어야 한다! break쓰면 안됨
return { ...state };
}
}
export default reducer;
5.redux를 불러와 보자
import React from "react";
import { useSelector } from "react-redux";
import CountView2 from "./CounterView2";
const CountView = () => {
// 저장소 값을 가져와 보자
// reacthook 함수
// useSelector 전역 상태값을 조회 할 때 사용
// 상태에서 카운트를 반환
// count가 변경되었을 때 리렌더링 된다.
// count값을 상태로 보고있음
const count = useSelector((state) => {
return state.count;
});
return (
<div>
{count}
<CountView2 />
</div>
);
};
export default CountView;
useSelector를 이용해 state의 key값을 불러와주자
6.아까 redux는 최종적으로 store에 저장되었다고 했는데 store의 구조를 보자
// 저장소 만들기
import { createStore } from "redux";
import reducer from "./reducer";
import { composeWithDevTools } from "redux-devtools-extension";
// 스토어의 전역상태가 변화하는걸 개발 모드로 확인가능한 툴
let store = createStore(reducer, composeWithDevTools());
export default store;
갖고온 reducer를 store로 선언해 export한다.
composeWithDevTools()는 브라우저에서 redux 전역 변수를 확인시켜주는 플러그인이다!
글이 많은 도움이 되었습니다, 감사합니다.