😇 프로젝트 준비하기
TodoTemplate
- 화면을 가운데 정렬 시켜주며 앱 타이틀을 보여준다.
- childred 내부 jsx를 props로 받아 와서 렌더링 해준다
TodoInsert
- 새로운 항목을 입력하고 추가할 수 있는 컴포넌트
- state로 인풋의 상태를 관리한다.
TodoListItem
- 각 할 일 항목에 대한 정보를 보여주는 컴포넌트.
- todo 객체를 props로 받아 와서 상태에 따라 다른 스타일의 UI를 보여준다
TodoList
- todos 배열을 props로 받아 온 후, map을 사용하여 여러 개의 TodoListItem으로 변환한다.
😎 UI 구성하기
Flexbox Froggy
😱 기능 구현하기
- 할 일 목록 만드는 기능을 구현한다
- 할 일을 추가, 제거, 수정 할 수 있는 기능이 담겨 있다.
App
import React, { useState, useRef, useCallback } from 'react';
import TodoTemplate from './components/TodoTemplate';
import TodoInsert from './components/TodoInsert';
import TodoList from './components/TodoList';
const App = () => {
const [todos, setTodos] = useState([
{
id: 1,
text: 'the basic of react',
checked: true,
},
{
id: 2,
text: 'the css of styling',
checked: true,
},
{
id: 3,
text: 'the todos of myself',
checked: false,
},
]);
const nextId = useRef(4);
const onInsert = useCallback(
(text) => {
const todo = {
id: nextId.current,
text,
checked: false,
};
setTodos(todos.concat(todo));
nextId.current += 1;
},
[todos],
);
const onRemove = useCallback(
(id) => {
setTodos(todos.filter((todo) => todo.id !== id));
},
[todos],
);
const onToggle = useCallback(
(id) => {
setTodos(
todos.map((todo) =>
todo.id === id ? { ...todo, checked: !todo.checked } : todo,
),
);
},
[todos],
);
return (
<TodoTemplate>
<TodoInsert onInsert={onInsert} />
<TodoList todos={todos} onRemove={onRemove} onToggle={onToggle} />
</TodoTemplate>
);
};
export default App;
TodoTemplate
import React from 'react';
import './TodoTemplate.scss';
export default function TodoTemplate({ children }) {
return (
<div className="TodoTemplate">
<div className="app-title">Schedule Table</div>
<div className="content">{children}</div>
</div>
);
}
TodoInsert
import React, { useState, useCallback } from 'react';
import { MdAdd } from 'react-icons/md';
import './TodoInsert.scss';
export default function TodoInsert({ onInsert }) {
const [value, setValue] = useState('');
const onChange = useCallback((e) => {
setValue(e.target.value);
}, []);
const onSubmit = useCallback(
(e) => {
onInsert(value);
setValue('');
e.preventDefault();
},
[onInsert, value],
);
return (
<form className="TodoInsert" onSubmit={onSubmit}>
<input
placeholder="what is your todo??"
value={value}
onChange={onChange}
></input>
<button type="submit">
<MdAdd></MdAdd>
</button>
</form>
);
}
TodoList
import React from 'react';
import TodoListItem from './TodoListItem';
import './TodoList.scss';
export default function TodoList({ todos, onRemove, onToggle }) {
return (
<div className="TodoList">
{todos.map((todo) => (
<TodoListItem
todo={todo}
key={todo.id}
onRemove={onRemove}
onToggle={onToggle}
/>
))}
</div>
);
}
TodoListItem
import React from 'react';
import {
MdCheckBoxOutlineBlank,
MdCheckBox,
MdRemoveCircleOutline,
} from 'react-icons/md';
import './TodoListItem.scss';
import cn from 'classnames';
export default function TodoListItem({ todo, onRemove, onToggle }) {
const { id, text, checked } = todo;
return (
<div className="TodoListItem">
<div className={cn('checkbox', { checked })} onClick={() => onToggle(id)}>
{checked ? <MdCheckBox /> : <MdCheckBoxOutlineBlank />}
<div className="text">{text}</div>
</div>
<div className="remove" onClick={() => onRemove(id)}>
<MdRemoveCircleOutline />
</div>
</div>
);
}