ReactJS 실무 활용 이야기
INDEX
‣ REACTJS를 선택하게된 계
기
‣ PROJECT 구성
‣ COMPONENT 개발
‣ REDUX
‣ TEST CODE
‣ FE FRAMEWORK
4명의 개발자
3개의 POC
FE 개발팀의 상황
짧은 개발기간(2개
월)
모바일&웹 모두 지
원
열악한 서비스 개발 환경
IE7 ~ IE8,
WINDOW XP
사용자가 50%
IT에 친화적이지 못한 업계
React 실무활용 이야기
IE7,8 사용자가
저렇게 많은데..
최신
FRAMEWORK를
사용해도 될까?
FE 개발자로서
시대에 뒤떨어질
것 같은데?
못먹어도 고?
지원군 NODE-WEBKIT 등장
‣ web application을 desktop application으로 만들어주는
라이브러리
‣ chromium기반의 패키징 application
‣ .exe, .app 으로 모두 생성 가능
IE10 미만의 브라우저를 사용하는 사용자들에게 window application을 제공
React 실무활용 이야기
React 실무활용 이야기
ReactJS를 선택하게된 이유
Component 기반 framework
하나의 부품으로 여러 사이트를 만들 수 있다면?
‣ 부품(component)의 규격
을 잘 정의해놓고 사용자
들이 쉽게 부품을 파악할
수 있다면 빠르게 조립해
서 결과물을 낼 수 있을 것
입니다.
WEB은 이미 COMPONENT화 되어 있습니다.
좀 더 SEMANTIC 하게 표현 할 수 있지 않을까요?
Virtual DOM
‣ 메모리상에 가상의 DOM Tree를 구축
‣ 데이터가 수정될 때 새로운 DOM Tree를 구축하고 이전 것과
비교
‣ 비교 후 변경사항이 있는 부분 수정
VIRTUAL DOM 동작
REFRESH없이 빠르게 DOM들을 RENDERING 할
수 있다.
ServerSide Rendering
프로젝트 환경과 맞지 않아 사용하지 않았습니다.
우리 프로젝트에는 REACTJS가 적
Component 기준으로 작업을 분배, 4명이 3개의 POC를 함께 담
화물의 상태를 실시간으로 Tracking 하는데 Virtual DOM 이 필
PROJECT 구성
BUILD TOOL
TESTING TOOL
DEV TOOL
FRAMEWORK
COMPONENT 개발
import {React, PropTypes} from ‘react’;
export default class ListComponent extends React.Component { //React.Component 상속
constructor(props) {
super(props); // [필수] 부모 생성자 호출 시 props를 파라미터로 전달
this.state = {}; //[필수] component 내의 state 값들은 반드시 constructor 내에서 초기화
this.testMethod = this.testMethod.bind(this); //[필수] 사용자가 생성한 method들은 binding처리
}
componentWillMount() {} //component의 lifecycle에 의한 callback method
componentWillReceiveProps(nextProps) {} //component의 lifecycle에 의한 callback method
testMethod() {}
render() {
return (<div class=“wrapper”> </div>); //반드시 하나의 element만 return 가능
return (<div class=“first”> </div><div class=“second”></div>);
}
};
PROPS? ST
import {React, PropTypes} from ‘react’;
import Child from ‘./ChildComponent’;
export default class ParentsComponent extends React.Component {
constructor(props) {
super(props);
this.state = {test: 1};
}
…..
render() {
return (<Child test={this.state.test} />);
}
}
Props는 외부에서 전달되는 값
보통 부모 Component에서 자식 Component로 값을 전달할 때 사용
export default class ChildComponent extends React.Component {
constructor(props) {
super(props);
this.state = {test: 3};
}
componentWillMount() {
this.test = this.props.test; // (o)
this.props.test = 2; // (x)
}
……
}
ChildComponent.propTypes = { test: PropTypes.number.isRequired };
props는 단방향으로 흐르기 때문에 rewrite 하지 못함
props의 type을 미리 정의해서 Component를 전반적으로 이해하는데 도움을 줄 수 있음
export default class ChildComponent extends React.Component {
constructor(props) {
super(props);
this.state = {test: 3};
}
componentWillMount() {
this.setState({test: 5}, () => {
//setState complete callback
});
}
render() {
return(<div class=“wrapper”>{this.state.test}</div>);
}
}
state는 component 내부에서 사용하는 전역 객체
setState를 통해서 state의 값을 업데이트, setState시에 component의 rerender를 유발
export default class ParentsComponent extends React.Component {
constructor(props) {
super(props);
this.state = {test: true};
}
click() { this.setState({test: false }); }
render() {
return (<Child test={this.state.test} onClick={()=>{this.click();}} />);
}
}
export default class ChildComponent extends React.Component {
constructor(props) {
super(props);
this.state = {test: true};
}
componentWillMount() { this.setState({test: this.props.test}); }
componentWillReceiveProps(nextProps) { this.setState({test: nextProps.te
render() {
return (<div class={show: this.state.test}> </div>);
}
}
React 실무활용 이야기
COMPONENT
….
export default class ListComponent extends React.Component {
….
renderList() {
const listItems = this.props.listItems;
return (() => {
if (listItems.length > 0) {
return listItems.map((item, i) => {
return (
<tr key={i}>
<td>{item.name}</td><td>{item.address}</td>
<td>{moment(item.date).format(‘YYYYMMDD’)}</td>
</tr>
);
});
}
})();
}
render() {
return (<div>{this.renderList()}</div>);
}
}
REDUX를 활용한 개
발
REDUX의 탄생
할 것 많고 관리할 것 많은 FE
‣ notification 상태 관리
‣ checkbox 상태관리
‣ comment list 데이터 관리
‣ loading bar 상태관리
etc ….
REDUX의 단방향 데이터 흐름
‣ UI 개발시에는 UI 로직만 신경써서 개발
‣ store라는 별도의 공간에 모든 필요한 데이터들을 state에 저장
‣ UI는 Action을 이용해서 Reducer를 호출하고 Action값에 따라 Reducer가 Store의 state를 업데이트
‣ UI에서는 변경된 state만을 접근하여 필요한 데이터만 사용
트럭킹 프로젝트를 하면서
서버로부터 받아오는 데이터들을 Redux를 활용해서 관리하기로 협의
Action.js
export const FETCH_SUPPLIER_ALL_LIST_START = ‘FETCH_SUPPLIER_LIST_START’;
export const FETCH_SUPPLIER_ALL_LIST_END = ‘FETCH_SUPPLIER_LIST_END’;
export const fetchSupplierAllList = (options) => {
return (dispatch) => {
dispatch({ type: FETCH_SUPPLIER_ALL_LIST_START });
return $.ajax(options).done((data) => {
dispatch({ type: FETCH_SUPPLIER_ALL_LIST_END, list: data});
})
….
}
}
Action은 Reducer에게 dispatch를 이용해 Action의 타입과 데이터들을 전달
dispatch를 이용해 Reducer를 제어/관리 할 수 있음
Reducer.js
import * as SA from ‘./Action’;
export const INITIAL_STATE = {
allList: []
};
export default function supplierReducer (state = INITIAL_STATE, action) {
switch (action.type) {
case SA.FETCH_SUPPLIER_ALL_LIST_END:
return Object.assign({}, state, {
allList: action.list
});
default:
return state;
}
};
reducer는 action으로부터 전달받은 type, data를 이용해서 state를 업데이트 시켜줌
이 때, 초기값을 변경시키지 않기위해 Object.assign 등을 활용해주면 좋음
component.js
import { React, PropTypes } from ‘react’;
import { connect } from ‘react-redux’;
import { fetchSupplierAllList } from ‘./Action’;
export class SupplierList extends React.Component {
componentWillMount() { this.props.fetchSupplierAllList(); }
render() { return (<div>{this.props.allList}</div>);}
}
SupplierList.propTypes = { allList: PropTypes.Array, fetchSupplierAllList: PropTypes.func.isRequired };
export default connect((state) => {
return {
allList: state.allList
};
}, {
fetchSupplierAllList
})(SupplierList);
어떤 component든 store의 state에서 데이터를 가져올 수 있다
USER
INFO
COMPO
NENT
login()
LOGIN
COMPO
NENT
ACTION REDUCE
R STORE
SERVER
Login api
user data
dispatch update
store의 state를 이용해서 서버에 대한 추가적인 요청 없이 user data
를 호출할 수 있다
TEST CODE
UI 테스트 코드
REDUX 테스트 코드
airbnb/enzyme
redux-mock-store
describe('<FreightHistorySearch />', () => {
const params = {
fetchFreightHistoryList: sinon.stub().returns({ done: sinon.spy() }),
pageInfo: {},
clickPersonalSearchBtn: sinon.stub().returns({ done: sinon.spy() }),
startDate: moment().date(1),
endDate: moment(),
handleDate: sinon.stub().returns({ done: sinon.spy() })
};
const wrapper = mount(<FreightHistorySearch {...params} />);
it('이번달 버튼 클릭 시, 이번달 목록이 나와야 함', () => {
wrapper.find('.thisMonth').at(0).simulate('click');
expect(wrapper.state().isClickedThisMonth).to.equal(true);
expect(wrapper.state().isClickedPrevMonth).to.equal(false);
});
it('지난달 버튼을 클릭 시, 지난달 목록이 나와야 함', () => {
wrapper.find('.lastMonth').at(1).simulate('click');
expect(wrapper.state().isClickedThisMonth).to.equal(false);
expect(wrapper.state().isClickedPrevMonth).to.equal(true);
});
});
export const FETCH_SUPPLIER_ALL_LIST_START = ‘FETCH_SUPPLIER_LIST_START’;
export const FETCH_SUPPLIER_ALL_LIST_END = ‘FETCH_SUPPLIER_LIST_END’;
export const fetchSupplierAllList = (options) => {
return (dispatch) => {
dispatch({ type: FETCH_SUPPLIER_ALL_LIST_START });
return $.ajax(options).done((data) => {
dispatch({ type: FETCH_SUPPLIER_ALL_LIST_END, list: data});
})
….
}
}
import * as SA from 'js/domain/supplier/supplierAction';
const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);
describe('Supplier thunks', () => {
it('fetchSupplierAllList()이 정상적으로 끝나면 FETCH_SUPPLIER_ALL_LIST_END 액션이 호출되어야 함', (done
const expectedActions = [
{
type: SA.FETCH_SUPPLIER_ALL_LIST_START
}, {
type: SA.FETCH_SUPPLIER_ALL_LIST_END,
list: []
}
];
const server = sinon.fakeServer.create();
server.respondWith("GET", "/ext/agency/freight/shippers", [200, {"Content-Type": "application/json"}, '[]']);
const store = mockStore({});
store.dispatch(SA.fetchSupplierAllList())
.then(() => {
expect(store.getActions()).to.eql(expectedActions);
done();
});
server.respond();
server.restore();
});
});
FE FRAMEWORK
태초에..
MVC
MVVM
component
FE FRAMEWORK 변천사
‣ Component 기반의 framework
‣ flux기반의 store 지원
‣ ES6, TypeScripe 와 같이 구조화된 스크립트 언어 지원
‣ VIRTUAL DOM 기반 framework
‣ ServerSide Rendering 지원
FE FRAMEWORK 4.0의 특징
React 실무활용 이야기
React 실무활용 이야기
React 실무활용 이야기
React 실무활용 이야기

More Related Content

PDF
#19.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
PDF
[국비지원교육/재직자/실업자환급교육/IT실무학원추천/스프링교육추천]#5.스프링프레임워크 & 마이바티스 (Spring Framework, M...
PDF
스프링컨트롤러예외처리,@ExceptionHandler, @ControllerAdvice
PDF
(스프링 초보자를 위한)스프링 DI관련 어노테이션,자동스캐닝 컴포넌트(Spring Framework Auto-Scanning Component)
PDF
#21.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
PDF
#22.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...
PPTX
E government framework
PDF
01.실행환경 실습교재(공통기반)
#19.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
[국비지원교육/재직자/실업자환급교육/IT실무학원추천/스프링교육추천]#5.스프링프레임워크 & 마이바티스 (Spring Framework, M...
스프링컨트롤러예외처리,@ExceptionHandler, @ControllerAdvice
(스프링 초보자를 위한)스프링 DI관련 어노테이션,자동스캐닝 컴포넌트(Spring Framework Auto-Scanning Component)
#21.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
#22.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...
E government framework
01.실행환경 실습교재(공통기반)

What's hot (20)

PPTX
5.Spring IoC&DI(DI와 관련된 어노테이션)
PDF
[자바학원/스프링교육학원/마이바티스학원추천/구로IT학원_탑크리에듀]#7.스프링프레임워크 & 마이바티스 (Spring Framework, M...
PDF
자바모델 클래스에 날개를달자_롬복(Lombok)
PDF
(스프링교육/마이바티스교육학원추천_탑크리에듀)#10.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)
PDF
[#9.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)]_재직자환급교육/실업자환급교육/구로IT학원/스프링교...
PDF
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
PDF
(국비지원/실업자교육/재직자교육/스프링교육/마이바티스교육추천)#13.스프링프레임워크 & 마이바티스 (Spring Framework, MyB...
PDF
#27.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...
PDF
04.실행환경 실습교재(화면처리)
PDF
(Spring Data JPA)식별자(@Id, Primary Key) 자동 생성, @GeneratedValue의 strategy 속성,Ge...
PDF
(IT실무교육/국비지원교육/자바/스프링교육추천)#15.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)
PDF
#32.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...
PDF
06.실행환경 실습교재(easy company,해답)
PDF
#16.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
PDF
#17.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
PDF
02.실행환경 실습교재(데이터처리)
PDF
(자바교육/스프링교육/스프링프레임워크교육/마이바티스교육추천)#2.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)
PDF
#2.SQL초보에서 Schema Objects까지_재직자/근로자환급/국비지원교육/IT실무교육/SQL기초교육/구로IT학원추천
PDF
(스프링초보자를위한)스프링 컨텍스트 설정과 관련된 어노테이션
5.Spring IoC&DI(DI와 관련된 어노테이션)
[자바학원/스프링교육학원/마이바티스학원추천/구로IT학원_탑크리에듀]#7.스프링프레임워크 & 마이바티스 (Spring Framework, M...
자바모델 클래스에 날개를달자_롬복(Lombok)
(스프링교육/마이바티스교육학원추천_탑크리에듀)#10.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)
[#9.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)]_재직자환급교육/실업자환급교육/구로IT학원/스프링교...
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
(국비지원/실업자교육/재직자교육/스프링교육/마이바티스교육추천)#13.스프링프레임워크 & 마이바티스 (Spring Framework, MyB...
#27.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...
04.실행환경 실습교재(화면처리)
(Spring Data JPA)식별자(@Id, Primary Key) 자동 생성, @GeneratedValue의 strategy 속성,Ge...
(IT실무교육/국비지원교육/자바/스프링교육추천)#15.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)
#32.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...
06.실행환경 실습교재(easy company,해답)
#16.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
#17.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
02.실행환경 실습교재(데이터처리)
(자바교육/스프링교육/스프링프레임워크교육/마이바티스교육추천)#2.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)
#2.SQL초보에서 Schema Objects까지_재직자/근로자환급/국비지원교육/IT실무교육/SQL기초교육/구로IT학원추천
(스프링초보자를위한)스프링 컨텍스트 설정과 관련된 어노테이션
Ad

Similar to React 실무활용 이야기 (20)

PDF
[React-Native-Seoul] React-Native 초심자를 위한 실습위주의 간단한 소개 및 구현법 안내
PDF
React Hooks 마법. 그리고 깔끔한 사용기
PPTX
[Codelab 2017] ReactJS 기초
PDF
React Native를 사용한
 초간단 커뮤니티 앱 제작
PDF
3.component 101
PPTX
Nodejs express
PPTX
Startup JavaScript 8 - NPM, Express.JS
PPTX
Node.js and react
PDF
ReactJS | 서버와 클라이어트에서 동시에 사용하는
PDF
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)
PPTX
One-day-codelab
PDF
Clean Front-End Development
PDF
2.Connect Sunshine to the Cloud - 시온고 안드로이드 스터디
PPTX
Vue.js 기초 실습.pptx
PDF
React 애플리케이션 아키텍처 - 아무도 알려주지 않아서 혼자서 삽질했다.
PPTX
Nodejs, PhantomJS, casperJs, YSlow, expressjs
PDF
overview of spring4
PPTX
[스프링 스터디 3일차] @MVC
PPTX
Flux 예제 분석 2
PDF
Meteor React Tutorial 따라하기
[React-Native-Seoul] React-Native 초심자를 위한 실습위주의 간단한 소개 및 구현법 안내
React Hooks 마법. 그리고 깔끔한 사용기
[Codelab 2017] ReactJS 기초
React Native를 사용한
 초간단 커뮤니티 앱 제작
3.component 101
Nodejs express
Startup JavaScript 8 - NPM, Express.JS
Node.js and react
ReactJS | 서버와 클라이어트에서 동시에 사용하는
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)
One-day-codelab
Clean Front-End Development
2.Connect Sunshine to the Cloud - 시온고 안드로이드 스터디
Vue.js 기초 실습.pptx
React 애플리케이션 아키텍처 - 아무도 알려주지 않아서 혼자서 삽질했다.
Nodejs, PhantomJS, casperJs, YSlow, expressjs
overview of spring4
[스프링 스터디 3일차] @MVC
Flux 예제 분석 2
Meteor React Tutorial 따라하기
Ad

React 실무활용 이야기

  • 2. INDEX ‣ REACTJS를 선택하게된 계 기 ‣ PROJECT 구성 ‣ COMPONENT 개발 ‣ REDUX ‣ TEST CODE ‣ FE FRAMEWORK
  • 3. 4명의 개발자 3개의 POC FE 개발팀의 상황 짧은 개발기간(2개 월) 모바일&웹 모두 지 원 열악한 서비스 개발 환경 IE7 ~ IE8, WINDOW XP 사용자가 50% IT에 친화적이지 못한 업계
  • 5. IE7,8 사용자가 저렇게 많은데.. 최신 FRAMEWORK를 사용해도 될까? FE 개발자로서 시대에 뒤떨어질 것 같은데? 못먹어도 고?
  • 6. 지원군 NODE-WEBKIT 등장 ‣ web application을 desktop application으로 만들어주는 라이브러리 ‣ chromium기반의 패키징 application ‣ .exe, .app 으로 모두 생성 가능 IE10 미만의 브라우저를 사용하는 사용자들에게 window application을 제공
  • 11. 하나의 부품으로 여러 사이트를 만들 수 있다면?
  • 12. ‣ 부품(component)의 규격 을 잘 정의해놓고 사용자 들이 쉽게 부품을 파악할 수 있다면 빠르게 조립해 서 결과물을 낼 수 있을 것 입니다.
  • 13. WEB은 이미 COMPONENT화 되어 있습니다. 좀 더 SEMANTIC 하게 표현 할 수 있지 않을까요?
  • 15. ‣ 메모리상에 가상의 DOM Tree를 구축 ‣ 데이터가 수정될 때 새로운 DOM Tree를 구축하고 이전 것과 비교 ‣ 비교 후 변경사항이 있는 부분 수정 VIRTUAL DOM 동작
  • 16. REFRESH없이 빠르게 DOM들을 RENDERING 할 수 있다.
  • 18. 프로젝트 환경과 맞지 않아 사용하지 않았습니다.
  • 19. 우리 프로젝트에는 REACTJS가 적 Component 기준으로 작업을 분배, 4명이 3개의 POC를 함께 담 화물의 상태를 실시간으로 Tracking 하는데 Virtual DOM 이 필
  • 21. BUILD TOOL TESTING TOOL DEV TOOL FRAMEWORK
  • 23. import {React, PropTypes} from ‘react’; export default class ListComponent extends React.Component { //React.Component 상속 constructor(props) { super(props); // [필수] 부모 생성자 호출 시 props를 파라미터로 전달 this.state = {}; //[필수] component 내의 state 값들은 반드시 constructor 내에서 초기화 this.testMethod = this.testMethod.bind(this); //[필수] 사용자가 생성한 method들은 binding처리 } componentWillMount() {} //component의 lifecycle에 의한 callback method componentWillReceiveProps(nextProps) {} //component의 lifecycle에 의한 callback method testMethod() {} render() { return (<div class=“wrapper”> </div>); //반드시 하나의 element만 return 가능 return (<div class=“first”> </div><div class=“second”></div>); } };
  • 25. import {React, PropTypes} from ‘react’; import Child from ‘./ChildComponent’; export default class ParentsComponent extends React.Component { constructor(props) { super(props); this.state = {test: 1}; } ….. render() { return (<Child test={this.state.test} />); } } Props는 외부에서 전달되는 값 보통 부모 Component에서 자식 Component로 값을 전달할 때 사용
  • 26. export default class ChildComponent extends React.Component { constructor(props) { super(props); this.state = {test: 3}; } componentWillMount() { this.test = this.props.test; // (o) this.props.test = 2; // (x) } …… } ChildComponent.propTypes = { test: PropTypes.number.isRequired }; props는 단방향으로 흐르기 때문에 rewrite 하지 못함 props의 type을 미리 정의해서 Component를 전반적으로 이해하는데 도움을 줄 수 있음
  • 27. export default class ChildComponent extends React.Component { constructor(props) { super(props); this.state = {test: 3}; } componentWillMount() { this.setState({test: 5}, () => { //setState complete callback }); } render() { return(<div class=“wrapper”>{this.state.test}</div>); } } state는 component 내부에서 사용하는 전역 객체 setState를 통해서 state의 값을 업데이트, setState시에 component의 rerender를 유발
  • 28. export default class ParentsComponent extends React.Component { constructor(props) { super(props); this.state = {test: true}; } click() { this.setState({test: false }); } render() { return (<Child test={this.state.test} onClick={()=>{this.click();}} />); } } export default class ChildComponent extends React.Component { constructor(props) { super(props); this.state = {test: true}; } componentWillMount() { this.setState({test: this.props.test}); } componentWillReceiveProps(nextProps) { this.setState({test: nextProps.te render() { return (<div class={show: this.state.test}> </div>); } }
  • 31. …. export default class ListComponent extends React.Component { …. renderList() { const listItems = this.props.listItems; return (() => { if (listItems.length > 0) { return listItems.map((item, i) => { return ( <tr key={i}> <td>{item.name}</td><td>{item.address}</td> <td>{moment(item.date).format(‘YYYYMMDD’)}</td> </tr> ); }); } })(); } render() { return (<div>{this.renderList()}</div>); } }
  • 33. REDUX의 탄생 할 것 많고 관리할 것 많은 FE ‣ notification 상태 관리 ‣ checkbox 상태관리 ‣ comment list 데이터 관리 ‣ loading bar 상태관리 etc ….
  • 34. REDUX의 단방향 데이터 흐름 ‣ UI 개발시에는 UI 로직만 신경써서 개발 ‣ store라는 별도의 공간에 모든 필요한 데이터들을 state에 저장 ‣ UI는 Action을 이용해서 Reducer를 호출하고 Action값에 따라 Reducer가 Store의 state를 업데이트 ‣ UI에서는 변경된 state만을 접근하여 필요한 데이터만 사용
  • 35. 트럭킹 프로젝트를 하면서 서버로부터 받아오는 데이터들을 Redux를 활용해서 관리하기로 협의
  • 36. Action.js export const FETCH_SUPPLIER_ALL_LIST_START = ‘FETCH_SUPPLIER_LIST_START’; export const FETCH_SUPPLIER_ALL_LIST_END = ‘FETCH_SUPPLIER_LIST_END’; export const fetchSupplierAllList = (options) => { return (dispatch) => { dispatch({ type: FETCH_SUPPLIER_ALL_LIST_START }); return $.ajax(options).done((data) => { dispatch({ type: FETCH_SUPPLIER_ALL_LIST_END, list: data}); }) …. } } Action은 Reducer에게 dispatch를 이용해 Action의 타입과 데이터들을 전달 dispatch를 이용해 Reducer를 제어/관리 할 수 있음
  • 37. Reducer.js import * as SA from ‘./Action’; export const INITIAL_STATE = { allList: [] }; export default function supplierReducer (state = INITIAL_STATE, action) { switch (action.type) { case SA.FETCH_SUPPLIER_ALL_LIST_END: return Object.assign({}, state, { allList: action.list }); default: return state; } }; reducer는 action으로부터 전달받은 type, data를 이용해서 state를 업데이트 시켜줌 이 때, 초기값을 변경시키지 않기위해 Object.assign 등을 활용해주면 좋음
  • 38. component.js import { React, PropTypes } from ‘react’; import { connect } from ‘react-redux’; import { fetchSupplierAllList } from ‘./Action’; export class SupplierList extends React.Component { componentWillMount() { this.props.fetchSupplierAllList(); } render() { return (<div>{this.props.allList}</div>);} } SupplierList.propTypes = { allList: PropTypes.Array, fetchSupplierAllList: PropTypes.func.isRequired }; export default connect((state) => { return { allList: state.allList }; }, { fetchSupplierAllList })(SupplierList);
  • 39. 어떤 component든 store의 state에서 데이터를 가져올 수 있다 USER INFO COMPO NENT login() LOGIN COMPO NENT ACTION REDUCE R STORE SERVER Login api user data dispatch update store의 state를 이용해서 서버에 대한 추가적인 요청 없이 user data 를 호출할 수 있다
  • 41. UI 테스트 코드 REDUX 테스트 코드 airbnb/enzyme redux-mock-store
  • 42. describe('<FreightHistorySearch />', () => { const params = { fetchFreightHistoryList: sinon.stub().returns({ done: sinon.spy() }), pageInfo: {}, clickPersonalSearchBtn: sinon.stub().returns({ done: sinon.spy() }), startDate: moment().date(1), endDate: moment(), handleDate: sinon.stub().returns({ done: sinon.spy() }) }; const wrapper = mount(<FreightHistorySearch {...params} />); it('이번달 버튼 클릭 시, 이번달 목록이 나와야 함', () => { wrapper.find('.thisMonth').at(0).simulate('click'); expect(wrapper.state().isClickedThisMonth).to.equal(true); expect(wrapper.state().isClickedPrevMonth).to.equal(false); }); it('지난달 버튼을 클릭 시, 지난달 목록이 나와야 함', () => { wrapper.find('.lastMonth').at(1).simulate('click'); expect(wrapper.state().isClickedThisMonth).to.equal(false); expect(wrapper.state().isClickedPrevMonth).to.equal(true); }); });
  • 43. export const FETCH_SUPPLIER_ALL_LIST_START = ‘FETCH_SUPPLIER_LIST_START’; export const FETCH_SUPPLIER_ALL_LIST_END = ‘FETCH_SUPPLIER_LIST_END’; export const fetchSupplierAllList = (options) => { return (dispatch) => { dispatch({ type: FETCH_SUPPLIER_ALL_LIST_START }); return $.ajax(options).done((data) => { dispatch({ type: FETCH_SUPPLIER_ALL_LIST_END, list: data}); }) …. } } import * as SA from 'js/domain/supplier/supplierAction'; const middlewares = [thunk]; const mockStore = configureMockStore(middlewares); describe('Supplier thunks', () => { it('fetchSupplierAllList()이 정상적으로 끝나면 FETCH_SUPPLIER_ALL_LIST_END 액션이 호출되어야 함', (done const expectedActions = [ { type: SA.FETCH_SUPPLIER_ALL_LIST_START }, { type: SA.FETCH_SUPPLIER_ALL_LIST_END, list: [] } ]; const server = sinon.fakeServer.create(); server.respondWith("GET", "/ext/agency/freight/shippers", [200, {"Content-Type": "application/json"}, '[]']); const store = mockStore({}); store.dispatch(SA.fetchSupplierAllList()) .then(() => { expect(store.getActions()).to.eql(expectedActions); done(); }); server.respond(); server.restore(); }); });
  • 46. ‣ Component 기반의 framework ‣ flux기반의 store 지원 ‣ ES6, TypeScripe 와 같이 구조화된 스크립트 언어 지원 ‣ VIRTUAL DOM 기반 framework ‣ ServerSide Rendering 지원 FE FRAMEWORK 4.0의 특징