$ npx create-react-app todo-app
로 프로젝트를 생성한 후 todo-app 디렉터리로 들어가서 필요한 라이브러리를 설치한다.
$ npm install node-ass classnames react-icons
프로젝트 최상위 디렉터리에 .prettierrc 파일을 생성한다.
{
"singleQuote": true,
"semi": true,
"useTabs": false,
"tabWidth": 2,
"trailingComma": "all",
"printWidth": 80
}
body {
margin: 0;
padding: 0;
background: #e9ecef;
}
import './App.css';
function App() {
return <div>Todo App을 만들자!</div>;
}
export default App;
TodoTemplate : 화면을 가운데에 정렬시켜 주며, 앱 타이틀(일정 관리)을 보여 준다.
children
으로 내부 JSX를props
로 받아 와서 렌더링 해준다.TodoInsert : 새로운 항목을 입력하고 추가할 수 있는 컴포넌트이다.
state
를 통해 인풋의 상태를 관리한다.TodoListItem : 각 할 일 항목에 대한 정보를 보여 주는 컴포넌트이다.
todo
객체를props
로 받아와서 상태에 따라 다른 스타일의 UI를 보여준다.TodoList :
todos
배열을props
로 받아 온 후, 이를 배열 내장 함수map
을 사용해서 여러 개의 TodoListItem 컴포넌트로 변환하여 보여준다.
//TodoTemplate.js
import React from 'react';
import './TodoTemplate.scss';
const TodoTemplate = ({ children }) => {
return (
<div className="TodoTemplate">
<div className="app-title">일정 관리</div>
<div className="content">{children}</div>
</div>
);
};
export default TodoTemplate;
TodoTemplate 컴포넌트를 App.js에서 불러와 렌더링한다.
// App.js
import './App.css';
import TodoTemplate from './components/TodoTemplate';
function App() {
return <TodoTemplate>Todo App을 만들자!</TodoTemplate>;
}
export default App;
TodoTemplate의 스타일을 작성한다.
// TodoTemplate.scss
.TodoTemplate {
width: 512px;
// width가 주어진 상태에서 좌우 중앙 정렬
margin-left: auto;
margin-right: auto;
margin-top: 6rem;
border-radius: 4px;
overflow: hidden;
.app-title {
background: #22b8cf;
color: white;
height: 4rem;
font-size: 1.5rem;
display: flex;
align-items: center;
justify-content: center;
}
.content {
background: white;
}
}
TodoInsert.js
import React from 'react';
import { MdAdd } from 'react-icons/md';
import './TodoInsert.scss';
const TodoInsert = () => {
return (
<form className="TodoInsert">
<input placeholder="할 일을 입력하세요" />
<button type="submit">
<MdAdd />
</button>
</form>
);
};
export default TodoInsert;
여기서 처음으로
react-icons
의 아이콘을 사용한다.
https://react-icons.netlify.com/#/icons/md 에서 사용하고 싶은 아이콘을 고른 뒤,import
구문을 사용하여 불러온 후 컴포넌트처럼 사용한다.import { 아이콘 이름 } from 'react-icons/md';
TodoInsert를 App에서 불러와 렌더링한다.
import './App.css';
import TodoInsert from './components/TodoInsert';
import TodoTemplate from './components/TodoTemplate';
function App() {
return (
<TodoTemplate>
<TodoInsert />
</TodoTemplate>
);
}
export default App;
그 결과 위와 같고 이제 스타일링을 해보자.
// TodoInsert.scss
.TodoInsert {
display: flex;
background: #495057;
input {
// 기본 스타일 초기화
background: none;
outline: none;
border: none;
padding: 0.5rem;
font-size: 1.125rem;
line-height: 1.5;
color: white;
&::placeholder {
color: #dee2e6;
}
// 버튼을 제외한 영역을 모두 차지하기
flex: 1;
}
button {
// 기본 스타일 초기화
background: none;
outline: none;
border: none;
background: #868e96;
color: white;
padding-left: 1rem;
padding-right: 1rem;
font-size: 1.5rem;
display: flex;
align-items: center;
cursor: pointer;
transition: 0.1s background ease-in;
&:hover {
background: #adb5bd;
}
}
}
결과는 아래!
// TodoListItem.js
import React from 'react';
import {
MdCheckBoxOutlineBlank,
MdCheckBox,
MdRemoveCircleOutline,
} from 'react-icons/md';
import './TodoListItem.scss';
const TodoListItem = () => {
return (
<div className="TodoListItem">
<div className="checkbox">
<MdCheckBoxOutlineBlank />
<div className="text">할 일</div>
</div>
<div className="remove">
<MdRemoveCircleOutline />
</div>
</div>
);
};
export default TodoListItem;
// TodoList.js
import React from 'react';
import TodoListItem from './TodoListItem';
import './TodoList.scss';
const TodoList = () => {
return (
<div className="TodoList">
<TodoListItem />
<TodoListItem />
<TodoListItem />
</div>
);
};
export default TodoList;
// App.js
import './App.css';
import TodoInsert from './components/TodoInsert';
import TodoList from './components/TodoList';
import TodoTemplate from './components/TodoTemplate';
function App() {
return (
<TodoTemplate>
<TodoInsert />
<TodoList />
</TodoTemplate>
);
}
export default App;
// TodoList.scss
.TodoList {
min-height: 320px;
max-height: 513px;
overflow-y: auto;
}
// TodoListItem.scss
.TodoListItem {
padding: 1rem;
display: flex;
align-items: center; // 세로 중앙 정렬
&:nth-child(even) {
background: #f8f9fa;
}
.checkbox {
cursor: pointer;
flex: 1; // 차지할 수 있는 영역 모두 차지
display: flex;
align-items: center;
svg {
// 아이콘
font-size: 1.5rem;
}
.text {
margin-left: 0.5rem;
flex: 1; // 차지할 수 있는 영역 모두 차지
}
// 체크되었을 때 보여 줄 스타일
&.checked {
svg {
color: #22b8cf;
}
.text {
color: #adb5bd;
text-decoration: line-through;
}
}
}
.remove {
display: flex;
align-items: center;
font-size: 1.5rem;
color: #ff6b6b;
cursor: pointer;
&:hover {
color: #ff8787;
}
}
// 엘리먼트 사이사이에 테두리를 넣어 줌
& + & {
border-top: 1px solid #dee2e6;
}
}
여기까지가 컴포넌트 스타일링 끝이다. 이제 다음엔 애플레케이션이 동작할 수 있도록 기능 구현을 하면 된다.