일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- https://velog.io/@velopert/create-typescript-react-component
- object
- toString
- 출처 : https://joshua1988.github.io/web-development/javascript/promise-for-beginners/
- 출처 : https://webdir.tistory.com/506
- 게시판
- http://jeonghwan-kim.github.io/dev/2019/06/25/react-ts.html
- Today
- Total
Back Ground
React - Redux 기초 작업 본문
긴 설명 보다 내가 보고 쓰기 편하게 단순하게
이해 할 수 있게 쓰겠다.
먼저 보일러 플레이트 중
create-react-app을 통해서 프로젝트를 생성 해 줄 것이다.
redux-setting 이라는 디렉토리로 만들었다
create-react-app redux-setting
이제 redux를 사용하기 위해 몇가지 모듈을 받아준다.
npm install redux react-redux
이제 불필요한 부분을 지워준다.
(기존 index 코드 부분이나 App 부분)
시작하기 전 리덕스의 구조를 생각해 둔다.
src 안에 디렉터로리를 나눠서 구조를 갖춰준다.
- actions
- components
- containers
- reducers
이제
리덕스 구조 그림을 참고하고 순서 대로 만들어 준다.
그러면 헤깔리지 않고 만들 수 있게 된다.
가장 먼저
ser > store.js를 만들어준다.
store
src/store.js
1 2 3 4 5 | import { createStore, applyMiddleware } from 'redux'; import { createLogger } from 'redux-logger'; const logger = createLogger(); export default createStore(/*reducer가 들어가 추가 될 곳,*/applyMiddleware(logger)); | cs |
tip : 여기서 redux-logger 는 redux의 상태를 로그로 보여주는 모듈이다. 로그 관리하고 보기 편하다 ( 선택 )
npm install redux-logger
store를 만들었으니 사용하기 위해 가장 먼저 실행되는 index.js에다가 store를 참조한다.
src/index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import * as serviceWorker from './serviceWorker'; import store from './store'; import { Provider } from 'react-redux'; ReactDOM.render( <Provider store={store}> <App /> </Provider> , document.getElementById('root')); serviceWorker.unregister(); | cs |
Provider는 리덕스를 컴퍼넌트로부터 연결하기 쉽게 만들어 준다.
store를 참조해서 만들어 준다.
다음은
action나 reducer를 만들어 주면 된다.
action쪽을 먼저 만들어 두는 편이 편하기 때문에 aciton을 먼저 작업한다.
action
actions 디렉토리에
- actionTyeps.js
- index.js
를 추가 해준다.
actionTyeps.js
1 2 | export const _CREATE = 'CREATE'; export const _UPDATE = 'UPDATE'; | cs |
actions/index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import * as types from './actionTyeps'; export const _create = () =>{ return { type: types._CREATE } } export const _update = (index) =>{/*인자는 리듀서에서 처리 필요 시 추가 */ return { type: types.UPDATE, index } } | cs |
다음은 Reducer를 만들어준다.
Reducer
reducers/reducer_setting.js
1 2 3 4 | export default [ {name:'test1' ,index:0, text:'setting_' ,boolean:false}, {name:'test2' ,index:0, text:'test_' ,boolean:false}, ] | cs |
state 초기값을 지정해 주면 된다.
디렉토리명이 reducer 라도 파일 네임앞에 reducer_를 붙여주는것이 좋다. (비슷한 파일명을 다루기 때문에 혼동을 방지하기 위함)
reducers/index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | import Reducer_setting from './reducer_setting';//state 초기값을 가져온다. import * as tyeps from '../actions/actionTyeps'; //액션 코드로 가져온다. import { combineReducers } from 'redux'; //다중 리듀서를 사용할때 리듀서를 넘겨주기 위한 용도 const root_reducer = { setting : Reducer_setting, } function redux_settingData (state = root_reducer, action){ //state는 reducer가 갖고 있는 state고 만약 없을시 초기값을 가져온다. //action은 dispatch함수로 connect를 통해서 들어 오게 된다. const {setting} = state; switch (action.type){//리듀서를 통해서 들어온 action case tyeps._CREATE: //acionTyeps에서 구분 // setState처럼 사용 할 부분 return { setting : //setting : 한 이유는 초기 setting을 했기에 변경 후에도 setting key를 유지하기 위함 {...setting}.concat(action.data) } case tyeps._UPDATE: //acionTyeps에서 구분 return { setting : setting.map( (key, i) => { if(i === action.index){ //action index.js에서 지정한 index return {...key, boolean:true} }else{ return {...key}; } }) } default: return state; //action을 이용하지 않을때 기본 this.props.setting을 사용할 때 사용 } } export default combineReducers({redux_settingData}); //다중으로 사용 되기 때문에 JSON타입 특성상 redux_settingData키로 값이 들어가기 때문에 this.propsredux_settingData.setting 가 된다. | cs |
이 부분 reducer의 핵심 부분이다. 리듀서를 호출할 때 이 함수를 통해서 변경된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | function redux_settingData (state = root_reducer, action){ const {setting} = state; switch (action.type){ case tyeps._CREATE: return { setting : {...setting}.concat(action.data) } case tyeps._UPDATE: return { setting : setting.map( (key, i) => { if(i === action.index){ return {...key, boolean:true} }else{ return {...key}; } }) } default: return state; } } | cs |
다중으로 사용 되기 때문에 JSON타입 특성상 redux_settingData키로 값이 들어가기 때문에 this.propsredux_settingData.setting가 된다.
1 | export default combineReducers({redux_settingData}); | cs |
src/store.js
1 2 3 4 5 6 | import { createStore, applyMiddleware } from 'redux'; import { createLogger } from 'redux-logger'; import reducers from './reducers'; const logger = createLogger(); export default createStore(reducers,applyMiddleware(logger)); | cs |
그 후 스토어에 reducer를 연결해준다.
다음은 dispatch를 리듀서로 보낸다.
dispatch
containers에 App.js를 만든다.
App.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import React, { PureComponent } from 'react'; import * as actions from '../actions'; import { connect } from 'react-redux'; class App extends PureComponent { render() { return ( <div className="App"> </div> ); } } //액션 생성 함수 준비 const mapToDispatch = (dispatch) =>({ onCreate: (data) => dispatch(actions._create(data)), onUpdate: (index) => dispatch(actions._update(index)) }); // 리덕스에 연결시키고 내보냅니다. export default connect(null, mapToDispatch)(App); | cs |
꼭 App.js가 아니더라도 필요한 부분의 컴포넌트에 넣으면 된다.
1 2 3 4 5 6 7 8 | //액션 생성 함수 준비 const mapToDispatch = (dispatch) =>({ onCreate: (data) => dispatch(actions._create(data)), onUpdate: (index) => dispatch(actions._update(index)) }); // 리덕스에 연결시키고 내보냅니다. export default connect(null, mapToDispatch)(App); | cs |
리덕스에 연결을 시켜 props로 받아서 사용이 가능하다.
App.js에서 리듀서를 통해서 받으면 props로 받을 수 있고
하위컴포넌트로 props로 보내면 된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | import React, { PureComponent } from 'react'; import * as actions from '../actions'; import { connect } from 'react-redux'; import Setting from '../components/setting';//컴포넌트 class App extends PureComponent { render(){ const {onCreate,onUpdate} = this.prop; return ( <div className="App"> <Setting onCreate={onCreate} onUpdate={onUpdate} /> </div> ); } } //액션 생성 함수 준비 const mapToDispatch = (dispatch) =>({ onCreate: (data) => dispatch(actions._create(data)), onUpdate: (index) => dispatch(actions._update(index)) }); // 리덕스에 연결시키고 내보냅니다. export default connect(null, mapToDispatch)(App); | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | import React, { PureComponent } from 'react'; import * as actions from '../actions'; import { connect } from 'react-redux'; class App extends PureComponent { render(){ console.log(this.props); return ( <div className="App"> {this.props.redux_settingData.setting.map( (key) => { return key.name })} <input type='button' onClick={()=>{ this.props._update(1) } }/> </div> ); } } //액션 생성 함수 준비 const mapToDispatch = (dispatch) =>({ _create: (data) => dispatch(actions._create(data)), _update: (index) => dispatch(actions._update(index)) }); function mapStateToProps(state){ //여기에서 state인자란 리듀서에서의 state이다. console.log("mapStateToProps : ",state); return state; } // 리덕스에 연결시키고 내보냅니다. export default connect(mapStateToProps, mapToDispatch)(App); | cs |
최종
src/store.js
1 2 3 4 5 6 | import { createStore, applyMiddleware } from 'redux'; import { createLogger } from 'redux-logger'; import reducers from './reducers'; const logger = createLogger(); export default createStore(reducers,applyMiddleware(logger)); | cs |
src/index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import React from 'react'; import ReactDOM from 'react-dom'; import App from './containers/App'; import * as serviceWorker from './serviceWorker'; import store from './store'; import { Provider } from 'react-redux'; ReactDOM.render( <Provider store={store}> <App /> </Provider> , document.getElementById('root')); serviceWorker.unregister(); | cs |
actions/actionTyeps.js
1 2 | export const _CREATE = 'CREATE'; export const _UPDATE = 'UPDATE'; | cs |
actions/index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import * as types from './actionTyeps'; export const _create = (data) =>{ return { type: types._CREATE, data } } export const _update = (index) =>{/* 인자는 리듀서에서 처리 시 추가 */ return { type: types._UPDATE, index } } | cs |
reducers/reducer_setting.js
1 2 3 4 5 | export default [ {name:'test1' ,index:0, text:'setting_' ,boolean:false}, {name:'test2' ,index:1, text:'test_' ,boolean:false}, ] | cs |
reducers/index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | import Reducer_setting from './reducer_setting';//state 초기값을 가져온다. import * as tyeps from '../actions/actionTyeps'; //액션 코드로 가져온다. import { combineReducers } from 'redux'; //다중 리듀서를 사용할때 리듀서를 넘겨주기 위한 용도 const root_reducer = { setting : Reducer_setting, } function redux_settingData (state = root_reducer, action){ //state는 reducer가 갖고 있는 state고 만약 없을시 초기값을 가져온다. //action은 dispatch함수로 connect를 통해서 들어 오게 된다. const {setting} = state; console.log("redux : ", state); switch (action.type){//리듀서를 통해서 들어온 action case tyeps._CREATE: //acionTyeps에서 구분 // setState처럼 사용 할 부분 return { setting : //setting : 한 이유는 초기 setting을 했기에 변경 후에도 setting key를 유지하기 위함 {...setting}.concat(action.data) } case tyeps._UPDATE: //acionTyeps에서 구분 return { setting : setting.map( (key, i) => { if(i === action.index){ //action index.js에서 지정한 index return {...key, boolean:true} }else{ return {...key}; } }) } default: return state; //action을 이용하지 않을때 기본 this.props.setting을 사용할 때 사용 } } export default combineReducers({redux_settingData}); //다중으로 사용 되기 때문에 JSON타입 특성상 redux_settingData키로 값이 들어가기 때문에 this.propsredux_settingData.setting 가 된다. | cs |
containers/App.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | import React, { PureComponent } from 'react'; import * as actions from '../actions'; import { connect } from 'react-redux'; class App extends PureComponent { render(){ console.log(this.props); return ( <div className="App"> {this.props.redux_settingData.setting.map( (key) => { return key.name })} <input type='button' onClick={()=>{ this.props._update(1) } }/> </div> ); } } //액션 생성 함수 준비 const mapToDispatch = (dispatch) =>({ _create: (data) => dispatch(actions._create(data)), _update: (index) => dispatch(actions._update(index)) }); function mapStateToProps(state){ //여기에서 state인자란 리듀서에서의 state이다. console.log("mapStateToProps : ",state); return state; } // 리덕스에 연결시키고 내보냅니다. export default connect(mapStateToProps, mapToDispatch)(App); | cs |
'Javascript > React.js' 카테고리의 다른 글
React - TypeScript로 생성하기 (2) | 2020.02.04 |
---|---|
React - 쉽게 css Module 설정 (0) | 2019.02.24 |
VSCODE - Debuging Mode ( Debugger for chrome ) (0) | 2018.12.16 |
ReactJS - redux-actions를 이용한 더 쉬운 액션 관리 (0) | 2018.12.14 |
ReactJS - Ducks 파일 구조 (0) | 2018.12.14 |