App.jsx
// import { useState } from 'react'
import './App.css'
import Header from './components/Header'
import Editor from './components/Editor'
import List from './components/List'
import { useState, useRef } from 'react'
const mockData = [
{
id : 0,
isDone: false,
content: "React 공부하기",
date: new Date().getTime(),
},{
id : 1,
isDone: false,
content: "React 공부하기1",
date: new Date().getTime(),
}, {
id : 2,
isDone: false,
content: "React 공부하기2",
date: new Date().getTime(),
}
]
function App() {
const [todos, setTodos] = useState(mockData);
const idRef = useRef(3);
const onCreate=(content)=>{
const newTodo = {
id:idRef.current++,
isDone:false,
content:content,
date:new Date().getTime(),
}
setTodos([newTodo,...todos]);
}
const onUpdate = (targetId) => {
//todos State의 값들 중에
//targetId와 일치하는 id를 갖는 투두 아이템의 isDone 변경
// 인수 : todos 배열에서 targetId와 일치하는 id를 갖는 요소의 데이터만 딱 바꾼 새로운 배열
setTodos(todos.map((todo)=>{
if(todo.id === targetId){
return{
...todo,
isDone: !todo.isDone
}
}
return todo
}))
}
const onDelete = (targetId) => {
// 인수 : todos 배열에서 targetId와 일치하는 id를 갖는 요소만 삭제한 새로운 배열
setTodos(todos.filter((todo)=>todo.id !== targetId))
}
return (
<div className='app'>
<Header></Header>
<Editor onCreate={onCreate}></Editor>
<List todos={todos} onUpdate={onUpdate} onDelete={onDelete}></List>
</div>
)
}
export default App;
Editor.jsx
import './Editor.css'
import { useState, useRef } from 'react'
const Editor = ({onCreate}) => {
const [content, setContent] = useState("");
const contentRef = useRef();
const onChangeContent = (e) => {
setContent(e.target.value);
}
const onSubmit = () => {
if (content===""){
contentRef.current.focus(); // 빈 값에 추가버튼 누르면 focus 작동되도록
return;
}
onCreate(content);
setContent(""); // 값 추가하면 빈 input 되도록 설정해주는 함수
}
const onKeydown = (e) => {
if(e.keyCode ===13 ){ //엔터치면 제출되도록
onSubmit();
}
}
return(
<div className="editor">
<input ref={contentRef} onKeyDown={onKeydown} value={content} onChange={onChangeContent} placeholder="새로운 Todo..."></input>
<button onClick={onSubmit}>추가</button>
</div>
);
}
export default Editor;
Header.jsx
import './Header.css';
const Header = () => {
return(
<div className="header">
<h3>오늘은🫶</h3>
<h1 >{new Date().toDateString()}</h1>
</div>
);
}
export default Header;
List.jsx
import "./List.css";
import TodoItem from "./TodoItem";
import { useState } from "react";
const List = ({todos, onUpdate, onDelete}) => {
const [search, setSearch] = useState("");
const onChangeSearch = (e) => {
setSearch(e.target.value);
}
const getFilterdData = () => {
if(search===""){return todos;}
return todos.filter((todo)=>todo.content.toLowerCase().includes(search.toLowerCase()));
}
const filteredTodos = getFilterdData();
return(
<div className="list">
<h4>🐰Todo List🐰</h4>
<input value={search} onChange={onChangeSearch} placeholder="검색어를 입력하세요 ..."></input>
<div className="todos.wrapper">
{filteredTodos.map((todo)=>{
return <TodoItem key={todo.id} {...todo} onUpdate={onUpdate} onDelete={onDelete}></TodoItem>
})}
</div>
</div>
);
}
export default List;
TodoItem.jsx
import "./TodoItem.css";
const TodoItem = ({id, isDone, content, date, onUpdate, onDelete}) => {
const onChangeCheckbox = () => {
onUpdate(id);
}
const onClickDeleteButton = () => {
onDelete(id);
}
return(
<div className="todoitem">
<input onChange={onChangeCheckbox} readOnly checked={isDone} type="checkbox"></input>
<div className="content">{content}</div>
<div className="date">{new Date(date).toLocaleDateString()}</div>
<button onClick={onClickDeleteButton}>삭제</button>
</div>
)
}
export default TodoItem;
728x90
'DEVELOPE > 앱개발시작하기' 카테고리의 다른 글
[20240513] 앱개발 시작하기 #26 | 투두리스트 이해해보기 (1) | 2024.05.15 |
---|---|
[20240510] 앱개발 시작하기 #24 | 개발자 도구 사용하기 (0) | 2024.05.10 |
[20240510] 앱개발 시작하기 #23 | 라이프사이클 (LifeCycle) | useEffect (0) | 2024.05.10 |
[20240509] 앱개발 시작하기 #22 | Counter App (1) | 2024.05.09 |
[20240508] 앱개발 시작하기 #21 | 리액트 훅 (0) | 2024.05.08 |