React 프로젝트를 시작하기 위해서는 먼저 Node.js와 npm을 설치해야합니다. 그리고 다음 명령어를 사용하여 React 프로젝트를 생성하세요.
npx create-react-app todo-app
프로젝트를 생성한 후, 프로젝트 폴더로 이동하여 다음 명령어를 입력하여 React 앱을 실행하세요.
cd todo-app
npm start
App.js 파일을 열고 Todo 리스트를 구현해보겠습니다.
import React, { useState } from 'react';
function App() {
const [todos, setTodos] = useState([]);
const handleAddTodo = (todo) => {
setTodos([...todos, todo]);
}
return (
<div>
<h1>Todo App</h1>
<ul>
{todos.map((todo, index) => (
<li key={index}>{todo}</li>
))}
</ul>
<input type="text" placeholder="Add Todo" onKeyUp={(e) => {
if (e.key === 'Enter') {
handleAddTodo(e.target.value);
e.target.value = '';
}
}} />
</div>
);
}
export default App;
이제 Todo 리스트를 추가할 수 있습니다. 입력 필드에 Todo를 입력하고 엔터를 누르면 리스트에 추가됩니다.
import React, { useState } from 'react';
function App() {
const [todos, setTodos] = useState([]);
const handleAddTodo = (todo) => {
setTodos([...todos, todo]);
}
const handleDeleteTodo = (index) => {
setTodos(todos.filter((todo, i) => i !== index));
}
return (
<div>
<h1>Todo App</h1>
<ul>
{todos.map((todo, index) => (
<li key={index}>
{todo}
<button onClick={() => handleDeleteTodo(index)}>Delete</button>
</li>
))}
</ul>
<input type="text" placeholder="Add Todo" onKeyUp={(e) => {
if (e.key === 'Enter') {
handleAddTodo(e.target.value);
e.target.value = '';
}
}} />
</div>
);
}
export default App;
이제 Todo 리스트에 추가된 각 항목 옆에 삭제 버튼이 추가됩니다. 클릭하면 항목이 삭제됩니다.
ul {
list-style-type: none;
padding: 0;
}
li {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
button {
background-color: red;
color: white;
border: none;
padding: 5px 10px;
border-radius: 5px;
cursor: pointer;
}
import React, { useState } from 'react';
function App() {
const [todos, setTodos] = useState([]);
const [editIndex, setEditIndex] = useState(null);
const [editValue, setEditValue] = useState('');
const handleAddTodo = (todo) => {
setTodos([...todos, todo]);
}
const handleDeleteTodo = (index) => {
setTodos(todos.filter((todo, i) => i !== index));
}
const handleEditTodo = (index, value) => {
setEditIndex(index);
setEditValue(value);
}
const handleUpdateTodo = () => {
const newTodos = [...todos];
newTodos[editIndex] = editValue;
setTodos(newTodos);
setEditIndex(null);
setEditValue('');
}
return (
<div>
<h1>Todo App</h1>
<ul>
{todos.map((todo, index) => (
<li key={index}>
{editIndex === index ? (
<>
<input type="text" value={editValue} onChange={(e) => setEditValue(e.target.value)} />
<button onClick={handleUpdateTodo}>Update</button>
</>
) : (
<>
{todo}
<div>
<button onClick={() => handleEditTodo(index, todo)}>Edit</button>
<button onClick={() => handleDeleteTodo(index)}>Delete</button>
</div>
</>
)}
</li>
))}
</ul>
<input type="text" placeholder="Add Todo" onKeyUp={(e) => {
if (e.key === 'Enter') {
handleAddTodo(e.target.value);
e.target.value = '';
}
}} />
</div>
);
}
export default App;
이제 각 Todo 항목에 대해 수정 버튼이 추가되었습니다. 클릭하면 Todo 항목이 입력 필드로 대체되며, 업데이트 버튼을 누르면 수정된 Todo가 저장됩니다.
import React, { useState } from 'react';
function App() {
const [todos, setTodos] = useState([]);
const [editIndex, setEditIndex] = useState(null);
const [editValue, setEditValue] = useState('');
const handleAddTodo = (todo) => {
setTodos([...todos, { text: todo, completed: false }]);
}
const handleDeleteTodo = (index) => {
setTodos(todos.filter((todo, i) => i !== index));
}
const handleEditTodo = (index, value) => {
setEditIndex(index);
setEditValue(value);
}
const handleUpdateTodo = () => {
const newTodos = [...todos];
newTodos[editIndex].text = editValue;
setTodos(newTodos);
setEditIndex(null);
setEditValue('');
}
const handleCompleteTodo = (index) => {
const newTodos = [...todos];
newTodos[index].completed = true;
setTodos(newTodos);
}
return (
<div>
<h1>Todo App</h1>
<ul>
{todos.map((todo, index) => (
<li key={index} className={todo.completed ? 'completed' : ''}>
{editIndex === index ? (
<>
<input type="text" value={editValue} onChange={(e) => setEditValue(e.target.value)} />
<button onClick={handleUpdateTodo}>Update</button>
</>
) : (
<>
{todo.text}
<div>
{!todo.completed && (
<>
<button onClick={() => handleEditTodo(index, todo.text)}>Edit</button>
<button onClick={() => handleDeleteTodo(index)}>Delete</button>
<button onClick={() => handleCompleteTodo(index)}>Complete</button>
</>
)}
</div>
</>
)}
</li>
))}
</ul>
<input type="text" placeholder="Add Todo" onKeyUp={(e) => {
if (e.key === 'Enter') {
handleAddTodo(e.target.value);
e.target.value = '';
}
}} />
</div>
);
}
export default App;
이제 각 Todo 항목에 대해 완료 버튼이 추가되었습니다. 클릭하면 Todo 항목이 완료되며, 완료된 Todo 항목은 취소선으로 표시됩니다.
이번 단계에서는 Todo 항목을 Local Storage에 저장하여, 페이지를 새로고침해도 Todo 항목이 유지되도록 하겠습니다
import React, { useState, useEffect } from 'react';
function App() {
const [todos, setTodos] = useState([]);
const [editIndex, setEditIndex] = useState(null);
const [editValue, setEditValue] = useState('');
useEffect(() => {
const storedTodos = JSON.parse(localStorage.getItem('todos'));
if (storedTodos) {
setTodos(storedTodos);
}
}, []);
useEffect(() => {
localStorage.setItem('todos', JSON.stringify(todos));
}, [todos]);
const handleAddTodo = (todo) => {
setTodos([...todos, { text: todo, completed: false }]);
}
const handleDeleteTodo = (index) => {
setTodos(todos.filter((todo, i) => i !== index));
}
const handleEditTodo = (index, value) => {
setEditIndex(index);
setEditValue(value);
}
const handleUpdateTodo = () => {
const newTodos = [...todos];
newTodos[editIndex].text = editValue;
setTodos(newTodos);
setEditIndex(null);
setEditValue('');
}
const handleCompleteTodo = (index) => {
const newTodos = [...todos];
newTodos[index].completed = true;
setTodos(newTodos);
}
return (
<div>
<h1>Todo App</h1>
<ul>
{todos.map((todo, index) => (
<li key={index} className={todo.completed ? 'completed' : ''}>
{editIndex === index ? (
<>
<input type="text" value={editValue} onChange={(e) => setEditValue(e.target.value)} />
<button onClick={handleUpdateTodo}>Update</button>
</>
) : (
<>
{todo.text}
<div>
{!todo.completed && (
<>
<button onClick={() => handleEditTodo(index, todo.text)}>Edit</button>
<button onClick={() => handleDeleteTodo(index)}>Delete</button>
<button onClick={() => handleCompleteTodo(index)}>Complete</button>
</>
)}
</div>
</>
)}
</li>
))}
</ul>
<input type="text" placeholder="Add Todo" onKeyUp={(e) => {
if (e.key === 'Enter') {
handleAddTodo(e.target.value);
e.target.value = '';
}
}} />
</div>
);
}
export default App;
이제 Todo 항목이 Local Storage에 저장되며, 페이지를 새로고침해도 Todo 항목이 유지됩니다.