import './App.css';
import React, { useState, useEffect } from 'react';
function App() {
const [todos, setTodos] = useState([]);
// Fetch todos on component mount
useEffect(() => {
fetch('http://localhost:8080/todos')
.then(response => response.json())
.then(data => setTodos(data))
.catch(error => console.error(error));
}, []);
// Function to add a new TODO item
const addTodo = (description) => {
fetch('http://localhost:8080/todos', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ description }),
})
.then(response => response.json())
.then(newTodo => setTodos([...todos, newTodo]))
.catch(error => console.error(error));
};
// Toggle completion
const toggleTodoComplete = (id) => {
const updatedTodos = todos.map(todo => {
if (todo.id === id) {
return { ...todo, completed: !todo.completed };
}
return todo;
});
setTodos(updatedTodos);
// Update completion
fetch(`http://localhost:8080/todos/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ completed: !todos.find(todo => todo.id === id).completed }),
})
.catch(error => console.error(error));
};
const deleteTodo = (id) => {
const filteredTodos = todos.filter(todo => todo.id !== id);
setTodos(filteredTodos);
fetch(`http://localhost:8080/todos/${id}`, {
method: 'DELETE'
})
.catch(error => console.error(error));
};
We have functions for creation, toggling completion, and deletion. To load the to-dos initially, we use the useEffect
effect to call the server for the initial set of to-dos when React first loads the UI. (See my introduction to React hooks to learn more about useEffect
.)
useState
lets us define the todos
variable. The Fetch API makes it pretty clean to define the back-end calls and their handlers with then
and catch
. The spread
operator also helps to keep things concise. Here’s how we set the new todos
list: