Tutorial: Aplicación React para Agregar Tareas-minimalista

 Voy a crear una aplicación React simple que permite agregar tareas a una lista usando un formulario con un solo input. Será minimalista y bien explicado paso a paso.

Estructura del Proyecto

text

react-todo-app/

  ├── src/

  │   ├── components/

  │   │   ├── TaskForm.js

  │   │   └── TaskList.js

  │   ├── App.js

  │   └── index.js

  ├── package.json

  └── README.md

Paso a Paso

1. Crear el proyecto

bash

npx create-react-app react-todo-app

cd react-todo-app

2. Limpiar archivos innecesarios

Elimina los archivos que no necesitamos para mantenerlo simple.

3. Crear el componente App.js

jsx

import React, { useState } from 'react';

import TaskForm from './components/TaskForm';

import TaskList from './components/TaskList';

import './App.css';


function App() {

  // Estado para almacenar la lista de tareas

  const [tasks, setTasks] = useState([]);


  // Función para agregar una nueva tarea

  const addTask = (taskText) => {

    // Crear un objeto tarea con texto y un ID único

    const newTask = {

      id: Date.now(), // Usamos timestamp como ID único

      text: taskText,

      completed: false

    };

    

    // Agregar la nueva tarea al estado

    setTasks([...tasks, newTask]);

  };


  return (

    <div className="App">

      <h1>Lista de Tareas</h1>

      <TaskForm onAddTask={addTask} />

      <TaskList tasks={tasks} />

    </div>

  );

}


export default App;

4. Crear el componente TaskForm.js

import React, { useState } from 'react';


function TaskForm({ onAddTask }) {

  // Estado para el valor del input

  const [taskText, setTaskText] = useState('');


  // Manejar el cambio en el input

  const handleChange = (e) => {

    setTaskText(e.target.value);

  };


  // Manejar el envío del formulario

  const handleSubmit = (e) => {

    e.preventDefault(); // Prevenir recarga de página

    // Validar que el input no esté vacío

    if (taskText.trim() === '') {

      alert('Por favor, escribe una tarea');

      return;

    }

    // Llamar a la función para agregar la tarea

    onAddTask(taskText);

    // Limpiar el input después de agregar

    setTaskText('');

  };


  return (

    <form onSubmit={handleSubmit} className="task-form">

      <input

        type="text"

        value={taskText}

        onChange={handleChange}

        placeholder="Escribe una nueva tarea..."

        className="task-input"

      />

      <button type="submit" className="add-button">

        Agregar Tarea

      </button>

    </form>

  );} export default TaskForm;

5. Crear el componente TaskList.js

jsx

import React from 'react';


function TaskList({ tasks }) {

  // Verificar si no hay tareas

  if (tasks.length === 0) {

    return <p className="empty-list">No hay tareas aún. ¡Agrega una!</p>;

  }


  return (

    <div className="task-list">

      <h2>Tareas ({tasks.length})</h2>

      <ul>

        {tasks.map((task) => (

          <li key={task.id} className="task-item">

            {task.text}

          </li>

        ))}

      </ul>

    </div>

  );

}


export default TaskList;

6. Crear el archivo App.css con estilos mínimos

css

.App {

  max-width: 500px;

  margin: 40px auto;

  padding: 20px;

  font-family: Arial, sans-serif;

}


h1 {

  text-align: center;

  color: #333;

}


.task-form {

  display: flex;

  margin-bottom: 20px;

}


.task-input {

  flex: 1;

  padding: 10px;

  font-size: 16px;

  border: 1px solid #ddd;

  border-radius: 4px 0 0 4px;

  outline: none;

}


.task-input:focus {

  border-color: #4CAF50;

}


.add-button {

  padding: 10px 20px;

  background-color: #4CAF50;

  color: white;

  border: none;

  border-radius: 0 4px 4px 0;

  cursor: pointer;

  font-size: 16px;

}


.add-button:hover {

  background-color: #45a049;

}


.task-list {

  background-color: #f9f9f9;

  border-radius: 4px;

  padding: 15px;

}


.task-list h2 {

  margin-top: 0;

  color: #555;

  border-bottom: 1px solid #eee;

  padding-bottom: 10px;

}


.task-list ul {

  list-style-type: none;

  padding: 0;

}


.task-item {

  padding: 10px;

  background-color: white;

  margin-bottom: 8px;

  border-radius: 4px;

  border-left: 4px solid #4CAF50;

  box-shadow: 0 2px 4px rgba(0,0,0,0.05);

}


.empty-list {

  text-align: center;

  color: #888;

  font-style: italic;

  padding: 20px;

}

7. Modificar el archivo index.js

jsx

import React from 'react';

import ReactDOM from 'react-dom/client';

import './index.css';

import App from './App';


const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(

  <React.StrictMode>

    <App />

  </React.StrictMode>

);

8. Crear index.css (opcional, para reset básico)

css

* {

  margin: 0;

  padding: 0;

  box-sizing: border-box;

}


body {

  background-color: #f5f5f5;

  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',

    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',

    sans-serif;

  -webkit-font-smoothing: antialiased;

  -moz-osx-font-smoothing: grayscale;

}


Explicación del Código

1. Componente App (Padre)

  • Usa useState para manejar el estado de las tareas

  • Pasa la función addTask como prop al componente TaskForm

  • Pasa el array tasks como prop al componente TaskList

2. Componente TaskForm (Hijo)

  • Tiene su propio estado local (taskText) para manejar el input

  • Valida que el input no esté vacío antes de agregar la tarea

  • Llama a onAddTask (prop recibida) cuando se envía el formulario

  • Limpia el input después de agregar la tarea

3. Componente TaskList (Hijo)

  • Recibe tasks como prop

  • Muestra un mensaje si no hay tareas

  • Usa map() para renderizar cada tarea como un elemento de lista

  • Cada tarea tiene un key único (ID) para optimización de React

4. Flujo de Datos

  1. El usuario escribe en el input en TaskForm

  2. Al enviar el formulario, TaskForm llama a addTask (pasada como prop desde App)

  3. addTask crea un nuevo objeto tarea y actualiza el estado en App

  4. El nuevo estado se pasa como prop a TaskList, que se re-renderiza con la nueva tarea



Ejecutar la Aplicación

bash

npm start

La aplicación estará disponible en http://localhost:3000

Características del Proyecto

  1. Simple: Solo un input para agregar tareas

  2. Modular: Componentes separados con responsabilidades claras

  3. Estado Centralizado: El estado principal está en el componente App

  4. Props y Callbacks: Comunicación entre componentes mediante props

  5. Estilo Mínimo: CSS básico pero funcional

Posibles Mejoras

Si quieres expandir el proyecto, podrías agregar:

  • Botón para eliminar tareas

  • Checkbox para marcar tareas como completadas

  • Almacenamiento en localStorage para persistencia

  • Filtros para mostrar tareas activas/completadas

Este proyecto es un excelente punto de partida para entender los conceptos fundamentales de React como componentes, estado, props y manejo de eventos.














1. Variable taskText en TaskForm

La variable taskText es el estado local del componente TaskForm que almacena lo que el usuario escribe en el campo de texto.

jsx

const [taskText, setTaskText] = useState('');

Cuando el usuario escribe en el input, handleChange actualiza este estado:

jsx

const handleChange = (e) => {

  setTaskText(e.target.value); // Aquí se guarda el texto

};

2. Flujo completo de taskText

  1. Usuario escribe → taskText se actualiza con cada tecla

  2. Usuario presiona "Agregar" → handleSubmit se ejecuta

  3. Se verifica que no esté vacío: if (taskText.trim() === '')

  4. Se pasa al componente padre: onAddTask(taskText)

    • onAddTask es la función addTask que viene de App.js

3. Cómo funciona addTask en App.js

jsx

const addTask = (taskText) => {

  // taskText es el parámetro que recibe desde TaskForm

  const newTask = {

    id: Date.now(), // ID único basado en timestamp

    text: taskText, // Aquí usa el texto recibido

    completed: false // Tarea no completada por defecto

  };

  

  // Agrega la nueva tarea al array existente

  setTasks([...tasks, newTask]);

};

Explicación del proceso:

  1. Recibe el texto: addTask(taskText) recibe el string que escribió el usuario

  2. Crea objeto tarea: Convierte el string en un objeto con estructura:

  3. js

{

  id: 1634567890123, // Número único (timestamp actual)

  text: "Hacer la compra", // Texto del usuario

  completed: false // Estado inicial

  1. }

  2. Actualiza el estado: Agrega el nuevo objeto al array tasks

    • [...tasks, newTask] crea un nuevo array con todas las tareas existentes + la nueva

4. Ejemplo concreto del flujo de datos

text

Usuario escribe: "Estudiar React"

taskText = "Estudiar React" (en TaskForm)

handleSubmit() llama a onAddTask("Estudiar React")

addTask("Estudiar React") (en App.js)

Crea objeto: {id: 1634567890123, text: "Estudiar React", completed: false}

setTasks([...tasks, {id: 1634567890123, text: "Estudiar React", completed: false}])

TaskList recibe el nuevo array y lo muestra

5. Resumen visual de la comunicación

text

TaskForm (Componente hijo)

   │

   │ Escribe usuario → taskText = "Texto"

   │

   │ Submit → onAddTask(taskText)

   │

   ↓

App (Componente padre)

   │

   │ Recibe: addTask("Texto")

   │

   │ Crea objeto tarea con el texto

   │

   │ Actualiza estado: setTasks()

   │

   ↓

TaskList (Componente hijo)

   │

   │ Recibe nuevo array de tareas

   │

   ↓

Renderiza lista actualizada

La variable taskText actúa como puente temporal que transporta el texto desde el input del usuario hasta el estado principal de la aplicación en App.js


Comentarios

Entradas más populares de este blog

9.3-Tutorial de Componentes React con Props -SSS

9.6-Ciclo de Vida de un Componente React

9-Componentes en React-estado