리덕스 첫 기초 포스팅에서는 개념을 파악하기 위해 모든 기능을 하나의 소스 코드에 넣었습니다. 즉 액션 정의, 리듀서 설정, 스토어 생성 등의 코드가 모두 한 곳에 있었습니다. 또한 하나의 리듀서를 사용하여 스토어 저장소도 나눠져 있지 않았습니다.
그래서 이번에는 코드를 분리하고 복수의 리듀서를 사용해 보겠습니다. 시간을 절약하기 위해 지난 시간에 했던 카운드 업 로직에 로그인 정보를 저장하는 정도의 기능을 추가하겠습니다. 아래 링크를 참고하세요~!
[Web프론트엔드/리액트] - [React] 리덕스(redux) 기능으로 데이터 관리하기 ① 기초
먼저 액션을 분리해보겠습니다. src/components 폴더 안에 actions 폴더를 만들고 이하 두 개의 소스를 추가합니다.
// ..\test_project\src\components\actions\countActions.js // 액션 타입 정의 export const SET_COUNT = 'countReducer/SET_COUNT'; export const RESET_COUNT = 'countReducer/RESET_COUNT'; // 액션 함수 정의 export const setCount = arg => ({ type: SET_COUNT, data: arg, }); export const resetCount = () => ({ type: RESET_COUNT, data: { count: 1, isTen: false }, });
// ..\test_project\src\components\actions\loginActions.js // 액션 타입 정의 export const SET_LOGIN = 'loginReducer/SET_LOGIN'; // 액션 함수 정의 export const setLogin = arg => ({ type: SET_LOGIN, data: arg, });
액션은 간단합니다. 리듀서와 연결하기 위해 액션 타입을 정의하고 dispatch()에서 사용할 액션 함수를 만듭니다. countReducer, loginReducer와 연결하기 때문에 명시적으로 이름을 붙여서 타입을 만들었습니다. 그럼 리듀서를 만들기 위해 액션처럼 src/components 폴더 안에 reducers 폴더를 만들고 이하 세 개의 소스를 추가합니다.
// ..\test_project\src\components\reducers\countReducer.js // 액션 타입 불러오기 import { SET_COUNT, RESET_COUNT } from "../actions/countActions"; // 데이터 정의 및 초기화 const initState = { count: 1, isTen: false, }; // 초기화 데이터로 리듀서 만들기 export default function reducer(state = initState, action) { const { type, data } = action; switch (type) { case SET_COUNT: { return { ...state, ...data, }; } case RESET_COUNT: { return { ...state, ...data, }; } default: return state; } }
// ..\test_project\src\components\reducers\loginReducer.js // 액션 타입 불러오기 import { SET_LOGIN } from "../actions/loginActions"; // 데이터 정의 및 초기화 const initState = { id: "", pass: "", setLogin: function () {}, }; // 초기화 데이터로 리듀서 만들기 export default function reducer(state = initState, action) { const { type, data } = action; switch (type) { case SET_LOGIN: { return { ...state, ...data, }; } default: return state; } }
// ..\test_project\src\components\reducers\index.js import countReducer from './countReducer'; import loginReducer from './loginReducer'; // 리듀서 모아서 내보내기 export default { countReducer, loginReducer, };
위에서 만든 액션을 불러와 리듀서에 붙여 줍니다. 중요한 부분은 state 데이터를 정의하고 초기화하는 부분인데 이렇게 리듀서 별로 만들어 놓으면 알기도 쉽고 조작하기도 편합니다. 실제로 사용하는 상위 소스에서도 다시 초기화가 가능합니다. 세 번째 소스인 index.js는 리듀서를 모아서 다음에 설명할 리덕스 스토어 생성에 사용하기 위함입니다.
// ..\test_project\src\components\reduxCreateStore.js import { createStore, combineReducers } from 'redux'; import { composeWithDevTools } from 'redux-devtools-extension'; import reducers from './reducers'; // 리덕스 스토어 생성 export default initStates => createStore( combineReducers(reducers), // 리듀서 결합 initStates, // 스테이터스 초기화 composeWithDevTools(), // 디버깅 미들웨어 );
마지막으로 리덕스 스토어를 생성하는 부분입니다. 위에서 만든 리듀서 모음을 불러들여 combineReducers() 함수를 이용해 결합해줍니다. 세 번째 인자는 바로 지난 시간에 했던 리덕스 디버깅 툴과 연결하는 부분입니다. 미들웨어라고 하는데 추후에 따로 포스팅하겠습니다. 그럼 모든 준비가 끝났으니 실제로 적용을 해볼 차례입니다.
// ..\test_project\src\components\CountUpRedux_new.js import React, { PureComponent } from "react"; import { Provider } from "react-redux"; import reduxCreateStore from "./reduxCreateStore"; import { setCount, resetCount } from "./actions/countActions"; import { setLogin } from "./actions/loginActions"; import Text from "./Text"; import Button from "./Button"; class CountUpRedux_new extends PureComponent { constructor(props) { super(props); // 콜백 함수 바인딩 this.countUp = this.countUp.bind(this); this.resetCount = this.resetCount.bind(this); this.setLogin = this.setLogin.bind(this); // 로그인 리듀서 초기화 const initStates_login = { id: "corona", pass: "dead4444", setLogin: this.setLogin, // 콜백 함수 연결 }; // 커스터마이징 함수로 스토어 생성 this.store = reduxCreateStore({ loginReducer: initStates_login }); } countUp() { // 스토어 데이터 const data = this.store.getState(); // 숫자 증가 const countTemp = data.countReducer.count + 1; let isTenTemp = data.countReducer.isTen; // 10이상이면 true if (countTemp >= 10) isTenTemp = true; // 액션 함수로 데이터 저장 this.store.dispatch(setCount({ count: countTemp, isTen: isTenTemp })); // 강제 갱신 (state 변경이 없어서) this.forceUpdate(); } resetCount() { this.store.dispatch(resetCount({ count: 1, isTen: false })); this.forceUpdate(); } setLogin() { this.store.dispatch(setLogin({ id: "아이디없음", pass: "ojimasio" })); this.forceUpdate(); } render() { // 프로바이더를 사용하여 자식에게 데이터 전달 const data = this.store.getState(); return ( <Provider store={this.store}> <React.Fragment> <Text>숫자값 : {data.countReducer.count}</Text> <br /> <Text>10이상 : {String(data.countReducer.isTen)}</Text> <br /> <Button name="countUp" onClick={this.countUp}> 카운트 </Button> <Button name="resetCount" onClick={this.resetCount}> 리셋 </Button> <br /> <Text>ID : {data.loginReducer.id}</Text> <br /> <Text>PASS : {data.loginReducer.pass}</Text> <br /> <Button name="login" onClick={data.loginReducer.setLogin}> 로그인 </Button> </React.Fragment> </Provider> ); } } export default CountUpRedux_new;
지난 시간에 했던 카운트 업 로직 그대로이며 간단하게 id, pass 데이터를 추가한 정도입니다. 중요한 부분은 생성자에 reduxCreateStore() 하는 곳입니다. 초기화하고 싶은 리듀서만 선택해서 데이터를 넣어주고 있습니다. 리듀서가 두 개 이기 때문에 데이터를 불러올 때도 countReducer와 loginReducer로 나눠져 있습니다. dispatch() 부분도 액션에 만들었던 함수를 사용하고 있습니다. 기초 시간에 했던 소스에서 많이 정리가 됐습니다. 그럼 스토리북 확인해보시죠!


오른쪽 위의 디버깅 툴 화면 처럼 액션 타입 이름이 리듀서 별로 나눠져 있고 아래 State탭 정보 또한 두 개의 리듀서로 나눠져 있는 것이 확인 가능합니다. 이렇듯 코드를 분리하는 것 뿐만이 아니라 스토어 저장 공간을 리듀서 별로 나누고 관리를 하면, 리덕스의 강력한 기능을 조금 더 효율적으로 사용 가능합니다. 그럼 다음 포스팅으로 또 뵙겠습니다~!?
ㅇ ㅏ~ 힘들다...
2020/10/27 - [Web프론트엔드/리액트] - [React] 리덕스(redux) 기능으로 데이터 관리하기 ④ 해시맵
'웹 프론트엔드 > React 리액트 (기초)' 카테고리의 다른 글
[React] 리덕스(redux) 기능으로 데이터 관리하기 ⑤ 커넥트 (0) | 2020.10.27 |
---|---|
[React] 리덕스(redux) 기능으로 데이터 관리하기 ④ 해시맵 (0) | 2020.10.27 |
[React] 리덕스(redux) 기능으로 데이터 관리하기 ② 디버깅 (0) | 2020.10.22 |
[React] 리덕스(redux) 기능으로 데이터 관리하기 ① 기초 (0) | 2020.10.16 |
[React] 컨텍스트(context) 기능으로 데이터 관리하기 (0) | 2020.10.14 |
댓글