Smart & Dumb Component
CRUD?
Create, Read, Update, Delete 더 자세한 설명이 필요없을것 같다.
구현에 앞서 생각해볼 문제가 있다.
필자는 CRUD 전반에 걸쳐 Form 을 재사용 하고 싶다.
재사용을 하려면 어떻게 해야 할까?
흐름도에 Smart Component
와 Dumb Component
가 있었던것을 기억하자.
재사용을 위해서 컴포넌트를 분리해야 한다.
여기서 드는 의문이 있다.
단순히 재사용에 목적만 있을까?
지난 포스팅을 보면 connect
를 통해 redux store
에 컴포넌트가 연결되어 있다고 했다.
모든 컴포넌트가 redux store
에 연결되어 있을 필요가 있을까?
state 를 사용하지 않는 컴포넌트가 store에 연결되어 있다면 store 에 낭비가
발생하는것이다.
여기서 Smart Component
와 dumb Component
의 구조상 차이점이 발생된다.
smart component
는 connect
를 통해 redux store
와 연결된 component
이고
dumb component
는 redux store
와 직접적인 연결 이 되지 않은 component
이다.
dumb
에 사전적의미를 찾아보면 멍청한 이란 뜻이 있다.
따라서 dumb component
는 혼자서 아무것도 할수없는 멍청한 컴포넌트로
이해하면 좋을것 같다.
About Component Detach
앞서 더미 데이터를 출력한 게시판 리스트는 이해를 돕기위해 컴포넌트를 분리 하지
않았다고 설명 했다. About.js 컴포넌트에서 dumb Component
를 분리 할것 이다.
render() 부분을 보자.
필자가 보기에 테이블이 멍청한 컴포넌트에 제격(?) 으로 보인다.
테이블을 멍청한 컴포넌트로 분리해보자.
about 폴더에 BoardList.js
파일을 생성 한다.
About.js 컴포넌트에 있는 div 이하 table 태그를 복붙 한다.
BoardList.js
import React, { PropTypes } from 'react';
const BoardList = ({contents}) => {
return (
<table className="table table-hover table-striped">
<thead>
<tr>
<th>No</th>
<th>Title</th>
<th>Author</th>
<th>Date</th>
</tr>
</thead>
<tbody>
{contents.map(content =>
<tr key={content.id}>
<td>{content.id}</td>
<td>{content.title}</td>
<td>{content.author}</td>
<td>{content.date}</td>
</tr>
)}
</tbody>
</table>
)
}
BoardList.propTypes = {
contents: PropTypes.array.isRequired
}
export default BoardList;
PART1 포스팅을 기억한다면 BoardList.js
의 구조 형식을 바로 알아 봤을것이다.
필자는 매번 render 함수안에 return을 해주기가 귀찮았다.
그래서 stateless
방식으로 component 를 구현해줬다.
dumb component는 state가 필요없다. 그래서 dumb component 는 stateless 방식으로
구현하는것이 구분하기도 편하고 알아보기 쉽다고 생각 한다.
이후 컴포넌트 파일들도 dumb component 는 stateless 방식으로 구현할 것이다.
이제 smart component가 될 About.js 를 보자.
분리한 BoardList component 를 import 시키고 render 영역을 다음과 같이
수정한다.
About.js
render() {
const contents = this.props.contents;
return (
<div>
<BoardList contents={contents} />
</div>
);
}
stateless 방식을 이용할때 주의점
About.js
에서 보면 contents={contents}
로 props 를 넘기고 있다.
이때 BoardList.js
로 넘어온 props 는 객체이다.
contents : array[4] 이런식으로 객체에 담겨서 넘어오게 된다.
이경우 ({contents}) 처럼 contents가 객체임을 명시해줘야 array 에 있는 map을 사용할수 있다.
About component
에서 dumb component
를 분리 했다.
About.js
가 smart_compoent
이고BoardList.js
가 dumb_component
인것을 한눈에 알수 있을것이다.
Form Component
앞서 About Component 로 부터 dumb component 를 분리 했다.
이제 폼을 만들면서 Smart 와 dumb component 가 어떻게 나뉘어 지는지
확인해보자.
폼은 작성자, 제목, 내용 3가지를 사용자로부터 입력받는다.
일단 부트스트랩을 이용해 폼을 만들어보자.
<div class="form-group">
<label for="author">Author</label>
<input type="text" class="form-control" id="author" />
</div>
<div class="form-group">
<label for="title">title</label>
<input type="text" class="form-control" id="title" />
</div>
<div class="form-group">
<label for="content">content</label>
<textarea id="content" class="form-control"></textarea>
</div>
<input type="submit" value="Save" class="btn btn-primary" />
이상태로 dumb component
를 정의할수도 있지만 폼 태그를 보면
input[type="text"]
형태의 태그가 반복 되는 경우가 많다.
필자가 작성한 폼의 경우에도 input[type="text"]
를 한번 이상
사용하기 때문에 분리하면 재사용 하기 좋을것 같다.
FormInput.js 를 생성 한다.
FormInput.js
import React, { PropTypes } from 'react';
const FormInput = ({name, label}) => {
return (
<div className="form-group">
<label htmlFor={name}>{label}</label>
<input type="text"
name={name}
className="form-control" />
</div>
);
}
FormInput.propTypes = {
name : PropTypes.string,
label: PropTypes.string
};
export default FormInput;
input[type="text"]
를 분리 했다.
그리고 BoardForm.js
를 생성 한다.
BoardForm.js
import React , { PropTypes } from 'react';
import FormInput from './FormInput';
const BoardForm = () => {
return (
<form>
<h1>Write</h1>
<FormInput name="authorId" label="Author" />
<FormInput name="title" label="Title" />
<div className="form-group">
<label for="content">Content</label>
<textarea id="content" className="form-control"></textarea>
</div>
<input
type="submit"
value="Save"
className="btn btn-primary"
/>
</form>
);
}
export default BoardForm;
폼 컴포넌트 틀이 완성 되었다.
그러나 BoardForm.js
가smart component
역할을 하진 않을 것이다.
smart component
가 필요 하다.
ManageBoard.js 파일을 생성한다.
ManageBoard.js
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import {bindActionCreators} from 'redux';
import BoardForm from './BoardForm';
export class ManageBoard extends Component {
constructor(props, context) {
super(props, context);
}
render() {
return (
<BoardForm />
)
}
}
function mapStateToProps(state, ownProps) {
return {
}
}
function mapDispatchToProps(dispatch) {
return {
}
}
export default connect(mapStateToProps, mapDispatchToProps)(ManageBoard);
BoardForm.js
는 ManageBoard.js
로부터 props 를 받아와서 상황별로
재사용이 가능하게 코드를 추가 할 것이다.
그전에 라우터를 추가해서 Write 폼이 제대로 나오는지 확인해보자.
테이블 헤드부분에 쓰기 버튼을 추가한다.
BoardList.js
에 상단에 react-router
를 호출해서 Link
태그를 추가해준다.
import { Link } from 'react-router'; //파일 상단부에 추가
/*thead 부분*/
<thead>
<tr>
<th colSpan="4" className="text-right">
<Link
to="/write"
className="btn btn-primary" >Write
</Link>
</th>
</tr>
<tr>
<th>No</th>
<th>Title</th>
<th>Author</th>
<th>Date</th>
</tr>
</thead>
해당 링크에 /write
라우터가 어떤 컴포넌트를 가르치는지 정의해줘야 한다.
routes.js 파일을 수정한다.
routers.js
import ManageBoard from './components/about/ManageBoard'; //추가
export default (
<Route path="/" component={Header}>
<IndexRoute component={Main} />
<Route path="main" component={Main} />
<Route path="about" component={About} />
<Route path="write" component={ManageBoard} /> //추가
</Route>
);
그럼 이제 화면을 확인해보자.
리스트 오른쪽 상단부분에 Write
버튼이 생겼고
버튼을 클릭하면 아래와 같은 Write
폼이 보일것 이다.
이번 포스팅에서는 smart / dumb component 에 대해서 살펴보고 이를 활용해
form을 분리 시켜봤다.
다음 포스팅에서는 생성한 form 컴포넌트들을 수정하면서 create 기능을 구현할것이다.
'FrontEnd > React,Redux' 카테고리의 다른 글
PART7:Simply build App with Redux - Read, Update / Redux Third Action (0) | 2016.09.29 |
---|---|
PART6:Simply build App with Redux - Create / Redux Second Action (0) | 2016.09.27 |
PART4:Simply build App with Redux - Data Flow (0) | 2016.09.22 |
PART3:Simply build App with Redux - Mock, webpack_loaders, Component (0) | 2016.09.22 |
PART2:Simply build App with Redux - Router, Redux Structure (0) | 2016.09.22 |