5-Actualizar una Tarea en React

 

Actualizar una Tarea en React: Guía Paso a Paso

En este post, implementaremos la funcionalidad para editar tareas en nuestra aplicación de lista de tareas. Integraremos la función handleUpdate con el código existente y explicaremos cada paso en detalle.


📌 Código Completo (Con Actualización Integrada)

jsx
Copy
Download
import { useState } from "react";
import Todo from "./todo";
import "./todoApp.css";

export default function TodoApp() {
  // Estados
  const [title, setTitle] = useState("");
  const [todos, setTodos] = useState([]);

  // Función para agregar una tarea
  function handleSubmit(e) {
    e.preventDefault();
    const newTodo = {
      id: Date.now(),
      title: title,
      completed: false,
    };
    setTodos([newTodo, ...todos]);
    setTitle("");
  }

  // Función para eliminar una tarea
  function handleDelete(id) {
    const filteredTodos = todos.filter((item) => item.id !== id);
    setTodos(filteredTodos);
  }

  // Función para actualizar una tarea
  function handleUpdate(id, newTitle) {
    const updatedTodos = todos.map((item) => {
      if (item.id === id) {
        return { ...item, title: newTitle }; // Actualiza solo el título
      }
      return item; // Mantiene los demás elementos igual
    });
    setTodos(updatedTodos);
  }

  return (
    <div className="todoContainer">
      {/* Formulario para agregar tareas */}
      <form onSubmit={handleSubmit} className="todoCreateForm">
        <input
          onChange={(e) => setTitle(e.target.value)}
          value={title}
          className="todoInput"
          placeholder="Escribe una nueva tarea"
        />
        <input type="submit" value="Crear tarea" className="buttonCreate" />
      </form>

      {/* Lista de tareas */}
      <div className="todosContainer">
        {todos.map((item) => (
          <Todo
            key={item.id}
            item={item}
            onDelete={() => handleDelete(item.id)}
            onUpdate={(newTitle) => handleUpdate(item.id, newTitle)} // Pasamos la función de actualización
          />
        ))}
      </div>
    </div>
  );
}

🔧 Explicación Paso a Paso

1. Función handleUpdate(id, newTitle)

Esta función recibe:

  • id → Identificador único de la tarea a editar.

  • newTitle → Nuevo texto de la tarea.

js
Copy
Download
function handleUpdate(id, newTitle) {
  const updatedTodos = todos.map((item) => {
    if (item.id === id) {
      return { ...item, title: newTitle }; // Actualiza solo el título
    }
    return item; // Mantiene los demás elementos igual
  });
  setTodos(updatedTodos);
}

📌 ¿Qué hace todos.map()?

  • Crea un nuevo array con las tareas actualizadas.

  • { ...item, title: newTitle } copia todas las propiedades de la tarea (idcompleted) y solo modifica title.

📌 ¿Por qué setTodos(updatedTodos)?

  • Actualiza el estado todos con el nuevo array.

  • React re-renderiza la lista automáticamente.


2. Pasando handleUpdate al Componente <Todo>

El componente TodoApp envía la función onUpdate como prop a cada <Todo>:

jsx
Copy
Download
<Todo
  key={item.id}
  item={item}
  onDelete={() => handleDelete(item.id)}
  onUpdate={(newTitle) => handleUpdate(item.id, newTitle)} // Pasamos la función de actualización
/>

📌 ¿Por qué (newTitle) => handleUpdate(item.id, newTitle)?

  • Pasamos una función personalizada que recibe el newTitle y llama a handleUpdate con el id correcto.


3. Implementación en el Componente <Todo>

Dentro de Todo.js, implementamos el modo edición:

jsx
Copy
Download
import { useState } from "react";

export default function Todo({ item, onDelete, onUpdate }) {
  const [isEditing, setIsEditing] = useState(false);
  const [editedTitle, setEditedTitle] = useState(item.title);

  // Función para guardar cambios
  function handleSave() {
    onUpdate(editedTitle); // Llama a onUpdate con el nuevo título
    setIsEditing(false);   // Desactiva el modo edición
  }

  return (
    <div className="todo">
      {isEditing ? (
        // Modo edición
        <div className="editMode">
          <input
            value={editedTitle}
            onChange={(e) => setEditedTitle(e.target.value)}
          />
          <button onClick={handleSave}>Guardar</button>
          <button onClick={() => setIsEditing(false)}>Cancelar</button>
        </div>
      ) : (
        // Modo visualización
        <div className="viewMode">
          <span>{item.title}</span>
          <button onClick={() => setIsEditing(true)}>Editar</button>
          <button onClick={onDelete}>Eliminar</button>
        </div>
      )}
    </div>
  );
}

📌 Flujo de Actualización:

  1. El usuario hace clic en "Editar" → Activa isEditing.

  2. Se muestra un input con el texto actual (editedTitle).

  3. El usuario edita el texto → setEditedTitle actualiza el estado local.

  4. Al hacer clic en "Guardar":

    • Llama a onUpdate(editedTitle) (que ejecuta handleUpdate en TodoApp).

    • React actualiza la lista y cierra el modo edición.


🎯 Diagrama de Flujo

text
Copy
Download
1. Botón "Editar" en `<Todo>` → Activa `isEditing`
2. Input muestra `editedTitle` (estado local)
3. Cambios en el input → Actualiza `editedTitle`
4. Botón "Guardar" → Ejecuta `onUpdate(editedTitle)`
5. `handleUpdate` en `TodoApp` modifica `todos`
6. React re-renderiza la lista con el cambio

💡 Mejoras Opcionales

  1. Validación de campos vacíos:

    js
    Copy
    Download
    function handleSave() {
      if (editedTitle.trim() === "") {
        alert("El texto no puede estar vacío");
        return;
      }
      onUpdate(editedTitle);
      setIsEditing(false);
    }
  2. Focus automático al editar:

    jsx
    Copy
    Download
    // Usa useRef y useEffect para enfocar el input
    const inputRef = useRef(null);
    useEffect(() => {
      if (isEditing) inputRef.current.focus();
    }, [isEditing]);
  3. Edición con Enter:

    jsx
    Copy
    Download
    <input
      value={editedTitle}
      onChange={(e) => setEditedTitle(e.target.value)}
      onKeyDown={(e) => e.key === "Enter" && handleSave()}
    />

🚀 Conclusión

  • Usamos map para actualizar el array sin mutar el estado original.

  • Pasamos funciones entre componentes (onUpdate) para mantener la lógica centralizada.

  • Modo edición local en <Todo> mejora la experiencia de usuario.

¡Con esto ya tienes un CRUD completo (Crear, Leer, Actualizar, Eliminar)! En próximos posts añadiremos filtros y persistencia en localStorage.

___________________________________________________________________

Dominando la Actualización de Estado en React: La Función handleUpdate

¡Saludos desarrolladores! 🌟 Continuemos explorando el flujo de datos en React, esta vez con una función clave para cualquier aplicación interactiva: actualizar estado de forma inmutable. Vamos a diseccionar handleUpdate y su viaje entre componentes.


🔍 La Función handleUpdate: Actualización Inmutable

javascript
Copy
Download
function handleUpdate(id, newTitle) {
  const updatedTodos = todos.map(item => {
    if (item.id === id) {
      return { ...item, title: newTitle }; // ¡Magia inmutabilidad!
    }
    return item;
  });
  setTodos(updatedTodos);
}

Qué hace:

  1. Mapea inteligentemente: Crea un nuevo array recorriendo todos.

  2. Encuentra el ítem: Compara IDs hasta hallar el elemento a modificar.

  3. Clona y actualiza: Usa el spread operator (...) para copiar el objeto y sobrescribir solo title.

  4. Conserva otros ítems: Devuelve los elementos no modificados intactos.

  5. Setea nuevo estado: Actualiza el estado con el array completamente nuevo.


⚙️ Comunicación entre Componentes: El Baile de las Props

Flujo completo:

  1. TodoApp define la lógica
    La función handleUpdate nace aquí porque el estado todos es su responsabilidad.

  2. Pasa la función como prop
    Al renderizar cada Todo, le entrega un "control remoto" para solicitar actualizaciones:

    jsx
    Copy
    Download
    <Todo 
      onUpdate={handleUpdate} 
      /* otras props */
    />
  3. Todo captura la acción del usuario
    Cuando el usuario edita:

    jsx
    Copy
    Download
    // En Todo.js
    function handleSubmit(e) {
      e.preventDefault();
      onUpdate(item.id, value); // ¡Dispara hacia arriba!
    }
  4. TodoApp ejecuta la actualización
    Recibe el ID y nuevo título, procesa el cambio y genera un NUEVO estado.

  5. Re-render automático
    React actualiza todos los componentes afectados con los nuevos datos.


🧩 ¿Por qué este flujo es PODEROSO?

  1. Inmutabilidad garantizada
    map() + spread operator aseguran que:

    • ✅ No mutamos el estado original

    • ✅ Detectamos cambios eficientemente

    • ✅ Facilitamos características de React como memoización

  2. Arquitectura de componentes óptima

    ResponsabilidadTodoApp (padre)Todo (hijo)
    EstadoDueño de todosRecibe solo su item
    Lógica de modificaciónDefine handleUpdateDispara onUpdate()
    UI/InteracciónLista contenedoraBotones/inputs
  3. Ventaja clave: Reutilización
    El componente Todo es 100% agnóstico de la lógica de actualización. ¡Podría usarse en otro proyecto con distinta implementación!


🚀 Ejemplo Visual del Flujo


 Errores comunes que evita este patrón

  1. Mutación directa del estado
    ❌ Peligroso: item.title = newTitle (modifica objeto existente)
    ✅ Seguro: return { ...item, title: newTitle } (nuevo objeto)

  2. Lógica duplicada
    Al centralizar en TodoApp, evitamos repetir código en cada componente hijo.

  3. Acoplamiento excesivo
    Todo no necesita saber cómo se almacenan las tareas (local storage, API, etc.), solo dispara eventos.


✨ Conclusión: Filosofía React en Acción

handleUpdate es un ejemplo perfecto de:

  • Flujo unidireccional: Datos bajan, acciones suben

  • Componentes purosTodo no modifica estado, solo notifica

  • Actualizaciones optimizadas: Inmutabilidad = Comparaciones rápidas

¡Este patrón es la base para gestionar estado en aplicaciones complejas con Redux o Context API

Comentarios

Entradas más populares de este blog

1-Sistema de Tareas en React

0-Gestión de estado en una aplicación de tareas

2-Agregar una Tarea a tu Lista de Tareas en React