// 리덕스
// 스토어, 액션 ,리듀서
// 스토어는 상태가 관리되는 오직 하나의 공간 컴포넌트와 별개로 store라는 공간이있어서
// 펼요한 상태값을 담아둔다.
// 컴포넌트에서 전역상태값이 필요할때 store에 접근해서 데이터를 가져온다.
// 액션은 스토어에 전달할 데이터를 자칭 액션을 사용해서 스토어에 데이터를 보내게된다.
// 액션은 자바 스크립트 객체 형식으로 만들어져 있으 dispatch 함수라는것을 사용해서 인자로 매개변수로
// 액션을 전달하면 리듀서가 호출되면서 매개변수로 액션을 받게되고
// dispatch(액션) => 리듀서가 호출되면서 리듀서에 액션을 전달하게된다.
// 리듀서 dispatch 함수를 통해 액션을 리듀서 함수에 전달한다.
// 리듀서 함수는 매개변수로 전달받은 액션이 뭔지보고 스토어에 상태를 업데이트 할지 여부를 결정
// 리덕스란
// 리액트에서 사용할수있는 하나의 라이브러리
// 리액트는 자식 컴포넌트에 props로 전달받은 값을 사용하는데
// 다른 컴포넌트와 데이터 공유를 직접하기힘듬 불가능하다.
// 그래서 공유해야할 데이터를 공유받는 자식컴포넌트들이 사용할때 공통적 부모 개념? 전역상태의 저장소 store
// 데이터를 공유할수이도록 만들어준것. 리액트의 데이터흐름은 단방향이라 이런단점을 보완하기 위해 만들었다.
// 리덕스는 사용하면 좋은데 사람들이 제일많이 어려워한다.
// 쉽게 말해 컴포넌트의 값을 요청하고 전달받는걸 직접 부모한테 전달받는게 아니라 컴포넌트의 값을 요청하고 전달하는것을 직접할수있다.
// 직접 전역 상태를 담고있는 store에 요청 전달한다.
// 스토어에 있는 데이터를 변수에 값을 넣는것처럼 바로 바꿀순없고 dispatch라는 함수를 사용해서 값을 전달할수있다.
// 리덕스의 동작 구조
// 컴포넌트 -> useDispatch -> Action -> Reducer -> store
// 컴포넌트가 Action을 보내고 Reducer 가 전달을 받고 값을 업데이트 할지 여부를 체크한다음 store의 값을 최신화 시켜준다.
// 액션을 리듀서가 캐치 리듀서가 판단한다음 저장.
// 액션은 동작할 기능 이름 (메뉴 이름)
// reducer 함수를 실행해서 내가 동작할 기능을 조건문으로 작성해둔 파일 (메뉴판)
// 컴포넌트가 어떤 Action을 실행시킬지 Reducer 함수로 받고 store의 값을 최신화 시켜준다.
// store의 값이 바뀌면 전역상태를 가져오고있는 컴포넌트들을 리랜더링된다.
// 설치 명령어
// npm i redux
// -------------------------------
// npm i react-redux
// 메인페이지 -> 로그인페이지 -> 음식주문 페이지 -> 마이페이지
// 주문한 음식들은 마이페이지에 보이고
// 로그인을 해야지 음식주문 페이지로 갈수있음. 마이페이지 도 물론 그렇다.
// react-router, react-redux
// props 값 전달 x
redux의 기본 원리?
action은 component에 에 지정되는 함수 실행같은것으로 on Click(handlerAdd) 와같이 속성을 부여해주면
handlerAdd 에는 dispatch함수를이용해서 redux의 reducer에 접근하게되고 판단을 거친뒤 store에 접근하게 된다.
import { createStore } from "redux";
let store = createStore(reducer,composeWithDevTools());
위코드와같이 store를 생성하고 매개변수로 reducer reducer를 준다. reducer 안에는 전역적인 state를 저장하듯
let init={
count: 0,
isLogin:false,
userState:{
userName:"",
userAge: 1,
}
,selectMenu:{
menu1Count:0,
menu2Count:0,
menu3Count:0,
menu4Count:0,
menu5Count:0,
}
}
function reducer(state=init,action){
console.log(action);
// 반환값이 무조건있어야함
// 함수안의 내용은 init으로 초기화한다?
console.log(state);
switch(action.type){
case "김치":
// 리듀서 함수의 반환값으로 저장소를 최신화 시켜준다.
// 저장소는 대기하다가 리듀서가 호출되면 값을 반환받아서 최신화 시켜줌
// ... 리듀서에서 반환된 값을 비교하는게 아니라 주소를 비교하기떄문에
// 값이 변해도 모름 주소가 바뀌지않으면 업데이트가 되지않느다.
return { ...state, selectMenu: { ...state.selectMenu, menu1Count: state.selectMenu.menu1Count + 1 } };
case "계란":
return {...state,count:state.count-1};
case "LOGIN" :
// ...state 초기 객체의 값을 복사하고
// count: 0,
// isLogin:false,
// userState:{
// userName:"",
// userAge: 1,
// }
//+ isLogin :ture 근데 이 키값이 이미 있다면 덮어 씌워진다.
// 전역상태를 개발하면서 브라우저의 개발자 모드로 전역상태로 바뀌는걸 실시간으로 확인하고싶음
// npm install redux-devtools-extension
return {...state,isLogin:action.payload};
case "LOGOUT" :
return {...state,isLogin:action.payload};
default:
return {...state};
}
}
export default reducer;
위와같이만들어준다. action으로 받는 type 은 보통 상태를 나타낼떄 사용되면 따라서 대문자로 쓰인다.
action.payload 에는 무엇이든 담을수있다. 보통 객체를 담거나 여러가지를 담는다.
위와같은 과정을 통해 만들어진 store는
import { Provider } from 'react-redux';
import store from './redux/store';
import { BrowserRouter } from "react-router-dom";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
// Provider 컴포넌트는 자식컴포넌트에 store를 주입해준다.
<BrowserRouter>
<Provider store={store}>
<App />
</Provider>
</BrowserRouter>
);
위와같이 최상위루트에 자식컴포넌트에 store를 주입하기 위한 방버으로 쓰인다.
이제 스토어에 저장된 값에 접근하고자한다면
import { useDispatch,useSelector } from 'react-redux’ 이런 함수들이 필요하다.
예시
const Main = () => {
const dispatch=useDispatch();
const navigate=useNavigate()
const handlerAdd = ()=>{
dispatch({type:"LOGIN",payload:true})
}
const handlerRemove=()=>{
// 객체를 전달하면 reducer의 action에 들어온s다.
// payload에는 그냥 담고싶은거 담으면된다.
dispatch({type:"LOGOUT",payload:false})
}
const userdata= useSelector(state=>state);
const Redirect = ()=>{
console.log(userdata);
return userdata.isLogin ===true ? navigate('/order') : <Navigate to={'/main'}/>
}
return (
<div>Main입니다!!!!!!!!
<button onClick={Redirect}>주문페이지로 이동</button>
<button onClick={handlerAdd}>로그인</button>
<button onClick={handlerRemove}>로그아웃</button>
{/* <Link to = {"/order"}> 주문페이지로 이동</Link> */}
</div>
)
}
export default Main
예시 메인에서는
useDispatch를 통해 store에있는 값에 접근하고
dispatch({type:"LOGIN",payload:true})
type에 맞는 프런트 화면을 이용해서 해당 함수가 동작한다면 reducer 에 action 으로 전달되어 swtich 문을 통한뒤 상황을 분별하게된다.
useSelector 사용해서 값을 읽어온다.
const userdata= useSelector(state=>state);
이때 arrrow func의 매개변수 이름은 중요하지않다. reducer안에 초기화된 값을 읽어올수있다.
'frontend > react' 카테고리의 다른 글
| react hook (0) | 2023.09.07 |
|---|---|
| 20230628~29 react시작 (1) | 2023.09.07 |