프로젝트 초기화

컴포넌트 생성

PageTemplate

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/d53e6cd2-7434-4550-bd77-18fb6f2ca907/Untitled.png

//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;
    }
}

TodoInput

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/1300e5d9-0a65-46e9-aa61-ba135ad9ae57/Untitled.png

//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;
}

TodoList

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/9bc49b43-11bd-40d8-978b-a148c6eec074/Untitled.png

//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;

컴포넌트 리렌더링 최적화