1. Component 계획
다음과 같이 4개의 컴포넌트로 To-do list 를 구성 하려고 한다.
- PageTemplate : UI의 전체 틀을 설정한다.
- InputTodo : 일정을 추가할때 사용하는 컴포넌트이다. input 폼과 추가 버튼이 있다.
- TodoItem : To-do list의 아이템 하나 하나가 된다.
- TodoList : 데이터를 TodoItem 컴포넌트로 리스트를 만드는 역할을 한다.
2. Component 생성하기
3. PageTemplate
//src/components/PageTemplate.js
import React from 'react';
import styles from './PageTemplate.scss';
import classNames from 'classnames/bind';
const cx = classNames.bind(styles);
const PageTemplate = ({ children }) => {
return (
<div className={cx('page-template')}>
<h1>To-do List</h1>
<div className={cx('content')}> {children} </div>
</div>)
};
export default PageTemplate;
import styles from './PageTemplate.scss'; 로 스타일을 import 한뒤 classNames 패키지로 bind한다.
To-do List의 가장 큰 기본틀을 구성하며 { children } 으로 자식요소들을 로드.
/*src/components/PageTemplate/PageTemplate.scss*/
@import "../../styles/utils";
.page-template {
margin-top: 5rem;
margin-left: auto;
margin-right: auto;
width: 500px;
background: white;
box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px, rgba(0,0,0,0.23);
padding-top: 2rem;
@media (max-width: 768px) {
margin-top: 1rem;
width: calc(100% - 2rem);
}
h1{
ext-align: center;
font-size: 4rem;
font-weight: 300;
margin: 0;
}
.content {
margin-top: 2rem;
}
}
//src/components/PageTemplate/index.js
export { default } from './PageTemplate';
/ndex.js 는 default 소스가 된다.
따라서 위와 같이 index.js 를 작성해 주면 상위 컴포넌트인 App.js에서 './PageTemplate/PageTemplate.js' 가 아닌 './PageTemplate' 로 import 할 수 있다.
4. InputTodo
//src/components/InputToto/InputTodo.js
import React from 'react';
import styles from './InputTodo.scss';
import classNames from 'classnames/bind';
const cx = classNames.bind(styles);
const InputTodo = ({ value, onChange, onInsert }) => {
const handleKeyPress = (e) => {
if (e.key === 'Enter') {
onInsert();
}
};
return (
<div className={cx('todo-input')}>
<input onChange={onChange} value={value} onKeyPress={handleKeyPress} />
<div className={cx('add-button')} onClick={onInsert}>추가</div>
</div>
)
};
export default InputTodo;
-이 컴포너트는 props를 3개 받는다.
- value : input 값으로 설정
- onChange : input 내용에 변경이 있을때 사용하는 이벤트
- onInsert : 추가 버튼을 눌렀을 때 실행하는 이벤트
-키보드 Enter 키 입력 이벤트를 위해서 handleKeyPress 메서드도 생성한다.
/*src/components/InputTodo/InputTodo.scss*/
@import "../../styles/utils";
.todo-input {
border-top: 1px solid $oc-gray-2;
border-bottom: 1px solid $oc-gray-2;
display: flex;
padding: 1rem;
input{
flex: 1;
font-size: 1.1rem;
outline: none;
border: none;
background: transparent;
border-bottom: 1px solid $oc-gray-4;
&:focus {
border-bottom: 1px solid $oc-cyan-6;
}
}
.add-button {
width: 5rem;
height: 2rem;
margin-left: 1rem;
border: 1px solid $oc-green-7;
color: $oc-green-7;
font-weight: 500;
font-size: 1.1rem;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
&:hover {
background: $oc-green-7;
color: white;
}
&:active {
background: $oc-green-8;
}
}
}
//src/components/InputTodo/index.js
export { default } from './InputTodo'
5. TodoItem
일정 정보를 렌더링 하는 TodoItem 컴포넌트이다.
//src/components/TodoItem/TodoItem.js
import React, { Component } from 'react';
import styles from './TodoItem.scss';
import classNames from 'classnames/bind';
const cx = classNames.bind(styles);
class TodoItem extends Component {
render() {
const { done, children, onToggle, onRemove } = this.props;
return (
<div className={cx('todo-item')} onClick={onToggle}>
<input className={cx('tick')} type="checkbox" checked={done} readOnly />
<div className={cx('text', { done })}>{children}</div>
<div className={cx('delete')} onClick={onRemove}>[지우기]</div>
</div>
);
}
}
export default TodoItem;
- done : 해당 일정이 완료했는지 체크
- children : 자식요소 (일정 내용)
- onToggle : 일정 완료/미완료 토글
- onRemove : 해당 일정 삭제
- const {done, children, onToggle, onRemove} = this.props; 비구조화 할당을 사용하여 아래에서 props를 사용할때 this.props.onToggle 과 같이 메서드 앞에 this.props 를 붙이는것을 생략할 수 있다.
/*src/components/TodoItem/TodoItem.scss*/
@import "../../styles/utils";
.todo-item {
padding: 1rem;
display: flex;
align-items: center;
cursor: pointer;
.tick {
margin-left: 1rem;
}
.text {
flex: 1;
word-break: break-all;
&.done {
text-decoration: line-through;
}
}
.delete {
margin-left: 1rem;
color: $oc-red-7;
font-size: 0.8rem;
&:hover {
color: $oc-red-5;
text-decoration: underline;
}
}
&:nth-child(odd) {
background: $oc-gray-0;
}
&:hover {
background: $oc-gray-1;
}
}
/*컴포넌트 사이에 위쪽 테두리를 설정*/
.todo-item + .todo-item {
border-top: 1px solid $oc-gray-1;
}
src/components/TodoItem/index.js
export { default } from './TodoItem';
6. TodoList
TodoList 컴포넌트는 데이터 배열을 컴포넌트 배열로 변환하여 렌더링 하는 역할만 한다. 데이터를 컴포넌트 배열로 변환하는 코드전에 더미 데이터를 넣어 컴포넌트가 정상적으로 렌더링 되는지 테스트 해본다.
//src/components/TodoList/TodoList.js
import React, { Component } from 'react';
import TodoItem from '../TodoItem';
class TodoList extends Component {
render() {
return (
<div>
<TodoItem done>첫번째 할일</TodoItem>
<TodoItem>두번째 할일</TodoItem>
</div>
);
}
}
export default TodoList;
//src/components/TodoList/index.js
export { default } from './TodoList';
7. App.js
//src/components/App.js
import React, { Component } from 'react';
import PageTemplate from './PageTemplate';
import InputTodo from './InputTodo';
import TodoList from './TodoList';
class App extends Component {
render() {
return (
<PageTemplate>
<InputTodo />
<TodoList />
</PageTemplate>
);
}
}
export default App;
App.js 에서 해당 컴포넌트를 로드하고 npm run start 명령어로 개발서버를 실행해보자.
정상적으로 컴포넌트들이 렌더링 되고 UI가 구성되는것을 확인할 수 있다.
'Javascript > projects' 카테고리의 다른 글
Counter (2) : 멀티 카운터 (0) | 2019.08.29 |
---|---|
Counter (1) : 카운터 만들기 (0) | 2019.08.29 |
Todo-list (4) : 리렌더링 최적화 하기 (0) | 2019.08.29 |
Todo-list (3) : 데이터 추가, 수정, 삭제 (0) | 2019.08.29 |
Todo-list (1) : 프로젝트 준비 (0) | 2019.08.29 |