React-redux를 사용하는 이유와 사용하는 방법 with Example
취업 후 열심히 배우고 일하느라 오랜만에 글을 쓴다.
회사생활이 너무 재미있어서 시간을 녹여버리고 있다.
어쨋든
Redux의 사용 이유
오늘은 React와 찰떡궁합 React-redux를 알아보자.
기존의 props를 과다 사용해서 프로젝트를 만들다보면
여러 컴포넌트가 쌓이고 쌓일수록 굉장히 복잡해지게 된다.
예를들어서 아래와 같이
export default function App() {
const [number, setNumber] = useState(0);
return (
<div className="App">
<h1>App</h1>
number : {number}
<Calculator1
onPlus={() => {
setNumber(number + 1);
}}
/>
<Result1 number={number} />
</div>
);
}
function Calculator1(props) {
return (
<div>
<h1>Calculator1</h1>
<Calculator2 onPlus={props.onPlus} />
</div>
);
}
function Calculator2(props) {
return (
<div>
<h1>Calculator2</h1>
<Calculator3 onPlus={props.onPlus} />
</div>
);
}
function Calculator3(props) {
return (
<div>
<h1>Calculator3</h1>
<button onClick={props.onPlus}>더하기</button>
</div>
);
}
function Result1(props) {
return (
<div>
<h1>Result1</h1>
<Result2 number={props.number} />
</div>
);
}
function Result2(props) {
return (
<div>
<h1>Result2</h1>
<Result3 number={props.number} />
</div>
);
}
function Result3(props) {
return (
<div>
<h1>Result3</h1>
number : {props.number}
</div>
);
}
이런 곂곂의 컴포넌트가 있다고 가정해보자.
Calculator3에서 버튼을 누르면
Calculator3 -> Calculator2 -> Calculator1 -> App
이런 경로로 액션이 전달되고 이 state를 다시
App -> Result1 -> Result2 -> Result3
이런 경로를 통해 number를 Result3이 전달 받게된다.
그럼 Calculator1, 2, Result1, 2는 이 정보를 알 필요가 없음에도
부모 컴포넌트라는 이유로 전달을 받아야하는 비효율성을 갖는다.
또한 정보를 Props로 전달받기 힘든 컴포넌트가 생길 수 있고
이처럼 재사용 하기 매우 까다롭다.
이 방식을 유선 연결이라고 생각할 때 바로 Redux는 무선으로 통신할 수 있는 기능이다.
실습
먼저 내 프로젝트에 설치해주자.
npm install redux react-redux
그 다음 Store를 만들어서 일종의 State저장소를 만들어 주는 것인데
function reduce(currentState, action) {
if (currentState === undefined) {
return {
number: 0,
};
}
const newState = { ...currentState };
if (action.type === "PLUS") {
newState.number++;
}
return newState;
}
이렇게 만들었다.
간단히 설명하자면 Store는 두가지 인자를 받는데,
currentState 현재 State값을 뜻하고,
action은 이 값을 어떻게 할지와 같은 일종의 명령이다.
안쪽엔 현재 상태가 undefined일 경우 기본값을 지정해주면 된다.
number를 0으로 기본값지정 해주었다.
이제 이 State를 어떻게 할지 적어야하는데
객체이기 때문에 새로운 newState값을 먼저 선언해주고
action.type이 PLUS로 들어올 경우 number를 +1 해주도록 했다.
그리고 새로운 State를 return.
이제 작성하던 Component에선 뭘해줘야하는가
Provider를 import하고 이 Store를 사용할 컴포넌트를 감싸야한다.
const Store = createStore(reduce);
export default function App() {
return (
<div className="App">
<h1>App</h1>
<Provider store={Store}>
<Calculator1 />
<Result1 />
</Provider>
</div>
);
}
전역변수로 Store를 선언해주고 Provider로 Calculator와 Result를 감싸주었다.
자 이제 가장 중요한 값을 바꿔주는 action과 내려받는 것을 해보자.
그전에 기존 props, onPlus 모두 지워줬다.
그리고 바로 Calculator3으로 가보자.
function Calculator3() {
const dispatch = useDispatch();
return (
<div>
<h1>Calculator3</h1>
<button
onClick={() => {
dispatch({ type: "PLUS" });
}}
>
더하기
</button>
</div>
);
}
dispatch를 선언해줘야 하는데 useDispatch도 import해주자.
그리고 onClick에 dispatch({type:"PLUS")} 만 적어주면
action = {type : "PLUS"}라는 객체가 Store로 입력된다.
물론 type 뒤에 데이터를 집어넣을 수도 있다.
dispatch({type:"UPDATE",data:{name:"LEE",age:20}})
이런식으로 사용하면 Store에서 action.data를 이용할 수 있다.
자 그럼 이제 Store의 State값을 가져와보자.
Result3을 보자.
function Result3() {
const number = useSelector((state) => state.number);
return (
<div>
<h1>Result3</h1>
number : {number}
</div>
);
}
너무 간단하다.
변수선언에 useSelector로 state.number를 가져오기만 하면
number라는 변수에 저장되는 것이다.
useSelector를 import하는 것도 잊지말자.
이제 더이상 필요없는 Component는 onClick에 대한 이벤트도, number State도
알 필요도 알 수도 없게 됐다.
훨씬 효율적인 프로젝트가 된듯하다.
그럼 결과를 살펴보자.
최종 코드
import { Provider, useSelector, useDispatch } from "react-redux";
import { createStore } from "redux";
import "./App.css";
function reduce(currentState, action) {
if (currentState === undefined) {
return {
number: 0,
};
}
const newState = { ...currentState };
if (action.type === "PLUS") {
newState.number++;
}
return newState;
}
const Store = createStore(reduce);
export default function App() {
return (
<div className="App">
<h1>App</h1>
<Provider store={Store}>
<Calculator1 />
<Result1 />
</Provider>
</div>
);
}
function Calculator1() {
return (
<div>
<h1>Calculator1</h1>
<Calculator2 />
</div>
);
}
function Calculator2() {
return (
<div>
<h1>Calculator2</h1>
<Calculator3 />
</div>
);
}
function Calculator3() {
const dispatch = useDispatch();
return (
<div>
<h1>Calculator3</h1>
<button
onClick={() => {
dispatch({ type: "PLUS" });
}}
>
더하기
</button>
</div>
);
}
function Result1() {
return (
<div>
<h1>Result1</h1>
<Result2 />
</div>
);
}
function Result2() {
return (
<div>
<h1>Result2</h1>
<Result3 />
</div>
);
}
function Result3() {
const number = useSelector((state) => state.number);
return (
<div>
<h1>Result3</h1>
number : {number}
</div>
);
}
오늘도 열심히 배우고 일해보자 화이팅!