이 코드는 React를 사용하여 Todo List 애플리케이션을 만드는 예제이다. 유데미에 한입 크기로 잘라 먹는 리액트 강의에서 나오는 프로젝트이다.
App.jsx: 애플리케이션의 메인 컴포넌트App.jsx는 전체 애플리케이션의 중심이다. 여기에서 모든 주요 상태를 관리하고, 다른 컴포넌트에 필요한 데이터를 전달하며, 할 일 목록의 생성, 업데이트, 삭제와 같은 주요 기능을 정의한다.
function App() {
const [todos, setTodos] = useState([]);
const idRef = useRef(0);
const onCreate = (content) => {
const newTodo = {
id: idRef.current++,
isDone: false,
content: content,
date: new Date().getTime(),
};
setTodos([newTodo, ...todos]);
};
const onUpdate = (targetId) => {
setTodos(
todos.map((todo) =>
todo.id === targetId ? { ...todo, isDone: !todo.isDone } : todo
)
);
};
const onDelete = (targetId) => {
setTodos(todos.filter((todo) => todo.id !== targetId));
};
return (
<div className="App">
<Header />
<Editor onCreate={onCreate} />
<List todos={todos} onUpdate={onUpdate} onDelete={onDelete} />
</div>
);
}
export default App;
상태관리 (useState):
todos: 할 일 목록을 관리하는 상태이다. 초기값은 빈 배열([])이며, 사용자가 할 일을 추가할 때마다 배열에 새로운 할 일이 추가된다.ID 관리 (useRef):
idRef: 할 일에 고유한 ID를 부여하기 위한 참조이다. useRef를 사용하여 값이 변경될 때 컴포넌트가 리렌더링되지 않도록 한다. idRef.current를 통해 현재 ID 값을 가져오고, 새로운 할 일을 추가할 때마다 이 값을 증가시킨다.할 일 생성 (onCreate):
content: 사용자가 입력한 할 일의 내용이다.todos 배열의 맨 앞에 추가한다. 여기서 할 일 객체는 고유 ID, isDone 상태, content, 생성 날짜(date)를 포함한다.할 일 업데이트 (onUpdate):
targetId: 업데이트할 할 일의 ID이다.isDone 상태를 토글한다. todos.map()을 사용하여 모든 할 일을 순회하고, targetId와 일치하는 할 일을 찾아 isDone 값을 반전시킨다. 이를 통해 할 일이 완료되었는지 여부를 쉽게 관리할 수 있다.할 일 삭제 (onDelete):
targetId: 삭제할 할 일의 ID이다.todos.filter()를 사용하여 주어진 ID와 일치하지 않는 모든 할 일들만 남겨서 새로운 배열을 생성한다. 이 배열이 todos로 업데이트되어, 화면에서 해당 할 일이 제거된다.Header.jsx: 헤더 컴포넌트Header.jsx는 애플리케이션의 상단에 위치하며, 오늘의 날짜와 함께 제목을 표시하는 역할을 한다. 이 컴포넌트는 주로 사용자가 현재 날짜를 쉽게 확인할 수 있도록 돕는 단순한 UI 요소를 제공한다.
import './Header.css';
const Header = () => {
return (
<div className="Header">
<h3>오늘은 📅</h3>
<h1>{new Date().toDateString()}</h1>
</div>
);
};
export default Header;
new Date().toDateString(): 현재 날짜를 문자열로 변환하여 표시한다. toDateString() 메서드는 날짜를 'Wed Aug 21 2024'와 같은 형식으로 변환해 준다.Editor.jsx: 할 일 입력 및 생성 컴포넌트Editor.jsx는 사용자가 새로운 할 일을 입력하고 추가할 수 있는 UI 컴포넌트이다. 할 일 추가 시 필요한 여러 가지 입력 및 유효성 검사를 처리한다.
import { useRef, useState } from 'react';
import './Editor.css';
const Editor = ({ onCreate }) => {
const [content, setContent] = useState('');
const contentRef = useRef();
const onChangeContent = (e) => {
setContent(e.target.value);
};
const onKeyDown = (e) => {
if (e.keyCode === 13) {
onSubmit();
}
};
const onSubmit = () => {
if (content === '') {
contentRef.current.focus();
return;
}
onCreate(content);
setContent('');
};
return (
<div className="Editor">
<input
ref={contentRef}
value={content}
onChange={onChangeContent}
onKeyDown={onKeyDown}
placeholder="새로운 Todo..."
/>
<button onClick={onSubmit}>추가</button>
</div>
);
};
export default Editor;
상태 관리 (useState):
content: 사용자가 입력한 텍스트를 관리하는 상태이다. 사용자가 입력 필드에 텍스트를 입력하면 onChangeContent 함수가 호출되어 이 상태를 업데이트한다.참조 (useRef):
contentRef: 입력 필드를 참조하기 위한 변수이다. 할 일을 추가할 때 내용이 비어 있으면 이 참조를 통해 입력 필드에 포커스를 줄 수 있다.할 일 추가 (onSubmit):
onCreate 함수를 호출하여 새로운 할 일을 생성하고, 입력 필드를 초기화 한다.Enter 키를 누르면 onKeyDown 이벤트 핸들러가 onSubmit을 호출하여 할 일이 추가되도록 한다.List.jsx: 할 일 목록 컴포넌트List.jsx는 할 일 목록을 필터링하여 화면에 표시하는 컴포넌트이다. 검색 기능을 포함하여, 사용자가 할 일을 쉽게 찾을 수 있도록 돕는다.
import { useState } from 'react';
import './List.css';
import TodoItem from './TodoItem';
const List = ({ todos, onUpdate, onDelete }) => {
const [search, setSearch] = useState('');
const onChangeSearch = (e) => {
setSearch(e.target.value);
};
const getFilteredData = () => {
if (search === '') {
return todos;
}
return todos.filter((todo) => {
return todo.content.toLowerCase().includes(search.toLowerCase());
});
};
const filteredTodos = getFilteredData();
return (
<div className="List">
<h4>Todo List 🌱</h4>
<input
value={search}
onChange={onChangeSearch}
placeholder="검색어를 입력하세요"
/>
<div className="todos-wrapper">
{filteredTodos.map((todo) => {
return (
<TodoItem
key={todo.id}
{...todo}
onUpdate={onUpdate}
onDelete={onDelete}
/>
);
})}
</div>
</div>
);
};
export default List;
상태 관리 (useState):
search: 사용자가 입력한 검색어를 관리하는 상태이다. 이 상태를 기반으로 할 일 목록을 필터링한다.검색 기능:
onChangeSearch: 검색어가 변경될 때마다 호출되어 search 상태를 업데이트한다.필터링 기능:
getFilteredData: 이 함수는 todos 배열을 검색어에 따라 필터링한다. 검색어가 비어있으면 모든 할 일을 반환하고, 그렇지 않으면 검색어를 포함하는 할 일들만 반환한다.할 일 목록 렌더링:
TodoItem 컴포넌트를 렌더링한다. TodoItem에는 각 할 일의 상태(isDone), 내용(content), 날짜(date), ID 등이 전달되며, 업데이트 및 삭제 함수도 함께 전달된다.TodoItem.jsx: 개별 할 일 컴포넌트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"
/>
<div className="content">{content}</div>
<div className="date">{new Date(date).toLocaleDateString()}</div>
<button onClick={onClickDeleteButton}>삭제</button>
</div>
);
};
export default TodoItem;
상태 변경 (onUpdate):
onChangeCheckbox 함수가 호출되어, onUpdate를 통해 상위 컴포넌트(App)에 상태 변경을 요청한다.onUpdate는 App.jsx에서 할 일의 isDone 상태를 토글하여 완료 상태를 관리한다.삭제 기능 (onDelete):
onClickDeleteButton 함수가 호출되어, onDelete를 통해 할 일이 삭제된다.App.jsx로 전달되며, todos 배열에서 해당 할 일이 제거된다.Editor.jsx에서 이를 처리하고, onCreate 함수를 통해 새로운 할 일을 생성한다.App.jsx의 todos 상태에 추가된다.List.jsx에서 필터링되어 표시되며, 검색 기능을 통해 사용자는 특정 할 일을 쉽게 찾을 수 있다.App.js에서 상태가 업데이트되고 목록이 갱신된다.