Redux는 리액트 뿐만 아니라 개별적으로 사용이 가능한 대표적인 상태관리 라이브러리이다.
리액트에서는 Redux를 사용함으로써 컴포넌트간의 데이터를 주고 받을때
state와 props로만 사용했을때 생기는 큰 불편함들을 모두 해결해줄 수 있다.
그럼 Redux는 어떻게 사용이 가능할까?
먼저, redux와 react-redux를 둘다 install을 해줘야 한다.
npm install redux react-redux
설치가 완료되었으면, 본격적으로 import를 해온다.
가장 먼저 createStore과 Provider를 import 해준다.
//이전 버젼의 redux를 사용할때 import { legacy_createStore as createStore } from 'redux'; //import { createStore } from 'redux';는 최신 redux을 쓰면서 새로운 코드를 작성할때 import { Provider } from 'react-redux';
createStore는 상태를 저장하는 유일한 한 곳인 store를 만들어주기 위해,
Provier는 store를 사용하고자 하는 컴포넌트를 지정해줄때 사용한다.
const store = createStore(/사용할 리덕스 함수/); ... function App(){ return ( <> <Provider store={store}> //사용하고자 하는 컴포넌트를 감싸며 store를 props로 주면 된다. <Component1 /> <Component2 /> <Provider /> </> ) }
위 두 과정을 모두 끝냈으면,
본격적으로 redux 함수를 만들어 줄 차례다.
const count = 1; //count라는 전달인자 생성, 1을 초기값으로 둠. const counterReducer = (state = count , action) => { switch(action.type){ case "INCREASE" : //타입 이름은 SNAKE_CASE처럼 대문자와 스네이크케이스로 써준다. return state + 1; //Action이 "INCREASE"일 경우 state + 1 case "DECREASE" : return state - 1; //Action이 "DECREASE"일 경우 state - 1 default : return state; //위의 해당되는 경우가 없다면 기존 state를 반환 } }
counterReducer가 완성이 되었다면
아까 만들었던 store에 전달인자로 넣어주고,
const store = createStore(counterReducer);
보통 많이 사용하는 방식인 각 type에 따라 함수를 만들어 준다.
export const increase = () => { return { type: "INCREASE", }; }; export const decrease = () => { return { type: "DECREASE", }; };
export시킨 각 함수를 이제 다른 파일에서 사용해줄 수 있다.
(다른 파일에서 import 해와서 사용하는 전제하에 코드를 적어보겠다.)
이제 할 차례는 본격적으로 store에 있는 데이터를 사용해볼 차례다.
useDispatch와 useSelector를 사용해서 store에 있는 상태를 바꾸거나 가져올 수 있다.
import { useDispatch, useSelector } from "react-redux" //가장 먼저 임포트 해주기
import { increase, decrease } from "App.js" //위에서 만들었던 코드들이 있는 파일
export default function App() {
const dispatch = useDispatch();
const plusNum = () => dispatch(increase()); //increase함수를 dispatch의 인자로 사용
const minusNum = () => dispatch(decrease());
const num = useSelector((state)=>state); //리턴한 state는 전체 객체를 의미함
return (
<div className="container">
<h1>{`Count: ${num}`}</h1>
<div>
<button className="plusBtn" onClick={plusNum}>
+
</button>
<button className="minusBtn" onClick={minusNum}>
-
</button>
</div>
</div>
);
}
만약 count가 객체라면 어떻게 따로따로 변경하거나 불러올 수 있을까?
const yonggal = {name: "yong", age: 18}; const counterReducer = (state = yonggal , action) => { switch(action.type){ case "nameChange" : return {...state, name: "pig"}; //기존 객체를 먼저 복사하고, 바꾸고자 하는 속성을 새로 생성한다. case "agePlusFive" : return {...state, age: state.age + 5}; default : return state; } }
각 타입에 따른 함수도 이미 만들었다고 전제하자.
nameChange(), agePlusFive()
import { useDispatch, useSelector } from "react-redux" /
import { nameChange, agePlusFive } from "App.js"
export default function App() {
const dispatch = useDispatch();
const onNameChange = () => dispatch(nameChange());
const onAgePlusFive = () => dispatch(agePlusFive());
const 바꾼이름 = useSelector((state)=>state.name);
const 바꾼나이 = useSelector((state)=>state.age);
//여기가 핵심이다.
//state.name , state, age로 객체에서 원하는 속성의 이름을 넣어서 각각 사용이 가능하다.
return (
<div className="container">
<h1>바꾼이름은? : {바꾼이름}</h1>
<h1>바꾼나이는? : {바꾼나이}</h1>
<div>
<button className="nameChange" onClick={onNameChange}>
이름 바꾸기!!!
</button>
<button className="agePlusFive" onClick={onAgePlusFive}>
나이 바꾸기!!!
</button>
</div>
</div>
);
}
지금까지 redux와 redux를 사용할 수 있는 방법과 문법에 대해 알아보았다.
위의 코드들에서는 편의를 위해 한개의 파일에서 store와 reducer등 여러가지를 정의했지만
코드의 가독성을 위해 각 기능별로 파일을 나누어 작성하는것이 좋다.