리액트 애플리케이션의 상태 관리 라이브러리
state(상태) : 컴포넌트 내부에서 관리되는 데이터
props drilling(프로퍼티 내리꽂기)
하위 컴포넌트가 깊어지고 전달하는 컴포넌트가 많아질 수록 props 를 추적하거나 유지보수하기 어려워진다.
React-Redux 는 이런 props drilling 을 막고 멀리 떨어진 컴포넌트도 중앙 데이터 저장소, Store 에서 직접 전달할 수 있다.
리덕스를 사용하면 state를 컴포넌트에 종속시키지 않고, 상태 관리를 컴포넌트의 바깥에서 관리 할 수 있게 된다.
전역 상태 저장소 제공
Props drilling 이슈 해결
컴포넌트는 store의 값을 직접적으로 바꾸거나 요청하지 못한다.
Action은 앱에서 스토어에 운반할 데이터를 말한다. (주문서)
Action을 Reducer에 전달하기 위해서는 dispatch() 메소드를 사용해야한다.
(액션은 자바스크립트 객체 형식으로 되어있다.)
Reducer가 주문을 보고 Store의 상태를 바꿔준다.
ex)
로그인 컴포넌트에서 "로그인 하기" 라는 행동을 리듀서에게 던져주고
리듀서가 케이스(행동지침)에 따라 Store를 업데이트 한다.
Store값이 바뀌면 자동으로 component가 바뀌면서 리렌더링 된다.
npm install redux
리덕스는 리액트에서만 쓰는 게 아니라 자바스크립트에서나 node.js 등 다양하게 사용되므로 리액트에서 리덕스를 사용할 땐 리액트-리덕스를 추가적으로 설치해주어야 한다.
npm i react-redux
https://react-redux.js.org/ 참고
<Provider store={store}>
<App />
</Provider>
아직 store를 정의하지 않아서 난 오류
https://ko.redux.js.org/introduction/getting-started 리덕스 문서 참고
store.js 파일 작성
import { createStore } from 'redux';
import reducer from './reducer/reducer';
// 앱의 상태를 보관하는 Redux 저장소 만들기
let store = createStore(reducer);
export default store;
reducer.js 파일 작성
let initialState = {
count: 0,
};
function reducer(state = initialState, action) {}
export default reducer;
다시 index.js 돌아가서 생성한 store
import 하기
import store from './redux/store';
useDispatch 훅 사용해서 reducer에 action 보내기
action을 보낼 땐 type은 필수적으로 작성하기
type: action의 이름
import logo from './logo.svg';
import './App.css';
import { useState } from 'react';
import { useDispatch } from 'react-redux';
function App() {
const [count, setCount] = useState(0);
const dispatch = useDispatch();
const increase = () => {
dispatch({ type: 'INCREMENT' });
setCount(count + 1);
};
return (
<div className="container">
<div className="wrap">
<h2>{count}</h2>
<button onClick={increase}>증가!</button>
</div>
</div>
);
}
export default App;
let initialState = {
count: 0,
};
function reducer(state = initialState, action) {
console.log('action은 뭐야?', action);
}
export default reducer;
결과 - > action은 객체이다.
이제 reducer에서 이 INCREMENT라는 액션이 올 때마다 store를 업데이트해주면 되는데
그 역할을 하는 부분이 return 이다.
그래서 항상 reducer는 store에게 return을 해주어야 한다.
reducer.js
function reducer(state = initialState, action) {
console.log('action은 뭐야?', action);
if (action.type === 'INCREMENT') {
return { ...state, count: state.count + 1 };
}
return { ...state }; // store는 return이 무조건 있어야 하므로
// reducer 함수에는 무조건 기본 리턴이 필요하다.
}
...state
은 만약 state가 여러개일 때 다른 state 값은 유지하되
count만 바꾸겠다는 뜻
....spread 문법을 통해 기존 객체 내용을 복사하여 새로운 객체에 전달 가능
store는 새로운 객체 주소를 전달받아야 자신이 업데이트 됐다는 걸 인식하게 된다.
헷갈리면 ...을 기본적으로 붙여주자요
이제 app.js에서 기존에 사용하던 state 부분을 없애고
Store에 있는 값을 가져다 적용하기 !!
useSelector
import 하기
useSelector 훅에서 reducer 에 있는 state객체 안 count라는 값을 가져온다.
const count = useSelector((state) => state.count);
import './App.css';
import { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
function App() {
// const [count, setCount] = useState(0);
const count = useSelector((state) => state.count);
const dispatch = useDispatch();
const increase = () => {
dispatch({ type: 'INCREMENT' });
// setCount(count + 1);
};
return (
<div className="container">
<div className="wrap">
<h2>{count}</h2>
<button onClick={increase}>증가!</button>
</div>
</div>
);
}
export default App;
결과
count가 잘 업데이트되어 반영되는 걸 확인할 수 있다.
컴포넌트를 추가적으로 만들고 테스트해보면
이젠 자식 컴포넌트에서 원하는 값을 받을 때 부모 컴포넌트에게서 props를 넘겨 받아 사용하는 게 아니라 원하는 값을 useSelector 훅을 통해 직접 값을 가져와 사용할 수 있다.
payload는 액션(Action) 객체의 속성 중 하나로
type과는 다르게 선택적인 요소이다.
데이터를 실어나르는 역할을 한다.
주로 리덕스에서 "payload"는 액션(Action) 객체의 속성 중 하나로 사용된다.
액션 객체는 해당 액션이 발생했음을 나타내는 유형(Type)과 함께 추가적인 데이터를 전달할 수 있는데, 이러한 추가 데이터가 "payload"이다.
예를 들어, 사용자가 특정 항목을 추가하는 액션을 생성할 때, 해당 항목의 데이터를 "payload"로서 액션 객체에 포함할 수 있다.
//app.js
const increase = () => {
dispatch({ type: 'INCREMENT', payload: { num: 5 } });
// setCount(count + 1);
};
//reducer.js
function reducer(state = initialState, action) {
console.log('action은 뭐야?', action);
if (action.type === 'INCREMENT') {
return { ...state, count: state.count + action.payload.num };
}
return { ...state };
}
결과 5씩 증가쓰
로그인 버튼 생성, 로그인 함수에서 dispatch 사용해서 LOGIN이라는 액션과 payload에 id,pw 데이터를 넘겨주고 reducer에서 받아 store를 업데이트 해주면
로그인 버튼 클릭 시 해당 id,pw 값이 렌더링 된다.
나중에 마이페이지 같은 부분에서
로그인 정보같은 것을 보여줄 때도 활용해보면 좋을 것 같다.
https://velog.io/@seungsang00/React-Redux-%EA%B8%B0%EC%B4%88
https://ko.redux.js.org/introduction/getting-started/
https://junvelee.tistory.com/97
https://medium.com/@heoh06/%EB%A6%AC%EC%95%A1%ED%8A%B8-redux%EC%99%80-%EC%82%AC%EC%9A%A9%EB%B2%95-731853fc3cd4