importar ‘./App.css’; importar React, { useState, useEffect } de ‘react’; función App() { const [todos, setTodos] = usarEstado([]); // Obtener todos en el montaje del componente useEffect(() => { fetch(‘http://localhost:8080/todos’) .then(response => response.json()) .then(data => setTodos(data)) .catch(error => console.error(error)); }, []); // Función para agregar un nuevo elemento TODO 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)); }; // Alternar finalización const toggleTodoComplete = (id) => { const updatedTodos = todos.map(todo => { if (todo.id === id) { return { …todo, completado: !todo.completed }; } return todo; }); setTodos(updatedTodos); // Actualizar finalización fetch(`http://localhost:8080/todos/${id}`, { method: ‘PUT’, headers: { ‘Content-Type’: ‘application/json’ }, body: JSON.stringify({ completado: !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)); }; Tenemos funciones para la creación, la finalización y la eliminación. Para cargar las tareas pendientes inicialmente, usamos el efecto useEffect para llamar al servidor para el conjunto inicial de tareas pendientes cuando React carga la IU por primera vez. (Consulta mi introducción a los ganchos de React para obtener más información sobre useEffect). useState nos permite definir la variable todos. La API Fetch hace que sea bastante claro definir las llamadas de back-end y sus controladores con then y catch. El operador spread también ayuda a mantener las cosas concisas. Así es como configuramos la nueva lista de tareas pendientes: