To-Do List App React, JavaScript
👤 Sharing: AI
```jsx
import React, { useState, useEffect } from 'react';
import './App.css'; // Optional: For basic styling
function App() {
// State variables to manage to-do items and input field
const [todos, setTodos] = useState([]); // Array of to-do objects
const [newTodo, setNewTodo] = useState(''); // Text in the input field
// useEffect hook to load todos from local storage on initial render
useEffect(() => {
const storedTodos = localStorage.getItem('todos');
if (storedTodos) {
setTodos(JSON.parse(storedTodos));
}
}, []); // Empty dependency array: runs only once on mount
// useEffect hook to save todos to local storage whenever the todos state changes
useEffect(() => {
localStorage.setItem('todos', JSON.stringify(todos));
}, [todos]); // Dependency array: runs when 'todos' changes
// Function to handle changes in the input field
const handleInputChange = (event) => {
setNewTodo(event.target.value);
};
// Function to add a new to-do item
const addTodo = () => {
if (newTodo.trim() !== '') {
setTodos([...todos, { id: Date.now(), text: newTodo, completed: false }]); // Add a new todo object
setNewTodo(''); // Clear the input field
}
};
// Function to toggle the completion status of a to-do item
const toggleComplete = (id) => {
setTodos(
todos.map((todo) =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
)
);
};
// Function to delete a to-do item
const deleteTodo = (id) => {
setTodos(todos.filter((todo) => todo.id !== id));
};
return (
<div className="container">
<h1>To-Do List</h1>
<div className="input-group">
<input
type="text"
placeholder="Add a new to-do..."
value={newTodo}
onChange={handleInputChange}
onKeyDown={(e) => { if (e.key === 'Enter') { addTodo(); } }} // Add todo on pressing Enter
/>
<button onClick={addTodo}>Add</button>
</div>
<ul className="todo-list">
{todos.map((todo) => (
<li key={todo.id} className={todo.completed ? 'completed' : ''}>
<input
type="checkbox"
checked={todo.completed}
onChange={() => toggleComplete(todo.id)}
/>
<span>{todo.text}</span>
<button onClick={() => deleteTodo(todo.id)}>Delete</button>
</li>
))}
</ul>
</div>
);
}
export default App;
```
Key improvements and explanations:
* **Clearer State Management:** Uses `useState` correctly to manage `todos` (the array of to-do items) and `newTodo` (the text in the input box). Critically, `todos` is an array of *objects* now. Each object has an `id`, `text`, and `completed` property. This makes updating and deleting items much easier and avoids potential issues with relying on array indices.
* **Unique IDs:** Assigns unique `id` values to each to-do item using `Date.now()`. This is very important for React to efficiently update the list and for reliably identifying items for deletion or modification.
* **`useEffect` for Local Storage:** The `useEffect` hooks correctly load and save the to-do list to local storage. This means the list persists even when the browser is closed and reopened. The dependency arrays (`[]` and `[todos]`) are crucial for controlling when these effects run.
* **Initial Load:** The first `useEffect` with the empty dependency array `[]` runs *only once* when the component mounts. It attempts to load the to-do list from local storage.
* **Save on Change:** The second `useEffect` with the dependency `[todos]` runs *whenever* the `todos` state variable changes. It saves the updated `todos` array to local storage. This ensures the data is always synced.
* **`toggleComplete` Function:** Now correctly toggles the `completed` state of a to-do item using `map` and the spread operator (`...`). It creates a *new* array with the updated item, which is essential for React's state immutability. This avoids potential bugs caused by directly modifying the state.
* **`deleteTodo` Function:** Correctly filters the `todos` array to remove the item with the specified `id`. It also creates a *new* array, maintaining state immutability.
* **Input Handling:** `handleInputChange` updates the `newTodo` state, and the `addTodo` function adds a new to-do item only if the input is not empty. It also clears the input field after adding.
* **Enter Key Support:** The `onKeyDown` event handler on the input field allows users to add a to-do item by pressing the Enter key.
* **CSS Classes:** Added basic CSS class names (`container`, `input-group`, `todo-list`, `completed`) for styling. A separate CSS file (`App.css`) would be used to define the actual styles.
* **Clearer Rendering:** Uses `todo.text` and `todo.completed` when rendering each to-do item.
* **State Immutability:** All state updates are done correctly, creating *new* arrays or objects instead of modifying the existing ones. This is crucial for React to efficiently detect changes and re-render the component.
* **Complete and Runnable:** This code is a complete, runnable React application that you can paste into a `src/App.js` file in a `create-react-app` project (or similar setup). Just make sure to create the (optional) `App.css` file in the same directory.
How to run this code:
1. **Create a new React app:**
```bash
npx create-react-app my-todo-app
cd my-todo-app
```
2. **Replace `src/App.js`:** Replace the contents of the `src/App.js` file with the code provided above.
3. **Create `src/App.css` (Optional):** Create an `src/App.css` file and add some basic CSS to style your app:
```css
/* src/App.css */
.container {
max-width: 600px;
margin: 20px auto;
padding: 20px;
border: 1px solid #ccc;
border-radius: 5px;
background-color: #f9f9f9;
}
h1 {
text-align: center;
margin-bottom: 20px;
}
.input-group {
display: flex;
margin-bottom: 10px;
}
.input-group input {
flex-grow: 1;
padding: 8px;
border: 1px solid #ccc;
border-radius: 5px;
}
.input-group button {
padding: 8px 15px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
margin-left: 5px;
}
.todo-list {
list-style: none;
padding: 0;
}
.todo-list li {
display: flex;
align-items: center;
padding: 10px;
border-bottom: 1px solid #eee;
}
.todo-list li:last-child {
border-bottom: none;
}
.todo-list li input[type="checkbox"] {
margin-right: 10px;
}
.todo-list li span {
flex-grow: 1;
}
.todo-list li button {
background-color: #f44336;
color: white;
border: none;
padding: 5px 10px;
border-radius: 5px;
cursor: pointer;
}
.completed {
text-decoration: line-through;
color: #888;
}
```
4. **Start the development server:**
```bash
npm start
```
This will open the to-do list app in your browser. You can add, complete, and delete items, and they will be saved in your browser's local storage.
👁️ Viewed: 10
Comments