프로젝트 초기화
- 프로젝트 생성: create-react-app
- 스타일 설정: css module 및 sass 적용
컴포넌트 생성
//src/component/PageTemplate/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>일정 괸리</h1>
<div className={cx('content')}>
{children}
</div>
</div>
)
}
export default PageTemplate;
//src/component/PageTemplate/PageTemplate.scss
.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 {
text-align: center;
font-size: 4rem;
font-weight: 300;
margin: 0;
}
.content {
margin-top: 2rem;
}
}
//src/component/TodoInput/TodoInput.js
import React from 'react';
import styles from './TodoInput.scss';
import classNames from 'classnames/bind';
const cx = classNames.bind(styles);
const TodoInput = ({ value, onChange, onInsert }) => {
const handlerKeyPress = e => {
if (e.key === 'Enter') {
onInsert();
}
}
return (
<div className={cx('todo-input')}>
<input onChange={onChange} value={value} onKeyPress={handlerKeyPress} />
<div className={cx('add-button')} onClick={onInsert}>추가</div>
</div>
)
}
export default TodoInput;
//src/component/TodoInput/TodoInput.scss
@import '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
}
}
}
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;
//src/component/TodoItem/TodoItem.scss
@import 'utils';
.todo-item {
padding: 1rem;
display: flex;
align-items: center;
cursor: pointer;
.tick {
margin-right: 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/TodoList
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;
컴포넌트 리렌더링 최적화