Crear una aplicación TODO en React es un excelente ejercicio para dominar los conceptos fundamentales de esta biblioteca. En este tutorial, exploraremos cómo configurar tu entorno de desarrollo, estructurar tu proyecto y desarrollar una aplicación que permita a los usuarios gestionar sus tareas diarias.
A lo largo de esta guía, veremos cómo implementar funciones esenciales como agregar una nueva tarea, eliminar tareas existentes y marcar tareas completadas. Además, se abordarán detalles sobre la organización de componentes, la gestión del estado con hooks y algunos consejos de estilo para mejorar la apariencia de la aplicación.
Antes de comenzar a escribir código, debes asegurarte de tener instalados Node.js y npm. Estos componentes son cruciales para la ejecución y manejo de dependencias en proyectos React. Una vez que tengas todo listo, abre tu terminal y ejecuta el siguiente comando para crear un proyecto nuevo utilizando create-react-app:
// Comando para crear una aplicación React llamada "todo-app"
npx create-react-app todo-app
cd todo-app
Esto configurará la estructura básica del proyecto, lo que incluye una carpeta "src" donde se ubicará todo el código fuente de tu aplicación.
Una buena organización de los archivos es esencial. Recomendamos crear una carpeta de componentes dentro de "src". Esto te ayudará a mantener cada parte de la aplicación bien segmentada:
| Carpeta | Descripción |
|---|---|
| src/components | Contendrá todos los componentes funcionales de la aplicación. |
| src/App.js | El archivo principal donde se orquesta la aplicación y se gestionan los componentes. |
| src/App.css | Archivo para estilos globales y específicos de la aplicación. |
Este componente se encarga de recoger la entrada del usuario, facilitando la creación de nuevas tareas. Usa el hook useState para manejar el valor del input y llama a una función para añadir la tarea a la lista.
// TodoInput.js
import React, { useState } from 'react';
const TodoInput = ({ addTodo }) => {
const [inputValue, setInputValue] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
if (inputValue.trim()) {
addTodo(inputValue);
setInputValue('');
}
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
placeholder="Agregar tarea"
/>
<button type="submit">Agregar</button>
</form>
);
};
export default TodoInput;
Cada tarea de la lista se representa mediante el componente TodoItem. Este componente no solo muestra el contenido de la tarea, sino que también incorpora funcionalidades para marcar la tarea como completada y eliminarla.
// TodoItem.js
import React from 'react';
const TodoItem = ({ todo, toggleCompleted, deleteTodo }) => {
return (
<li>
<div>
<input
type="checkbox"
checked={todo.completed}
onChange={() => toggleCompleted(todo.id)}
/>
<label style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}>
{todo.text}
</label>
</div>
<button onClick={() => deleteTodo(todo.id)}>Eliminar</button>
</li>
);
};
export default TodoItem;
Este componente agrupa todos los TodoItem y se encarga de renderizarlos en un formato de lista. Cada ítem de la lista se pasa junto con las funciones necesarias para modificar su estado.
// TodoList.js
import React from 'react';
import TodoItem from './TodoItem';
const TodoList = ({ todos, toggleCompleted, deleteTodo }) => {
return (
<ul>
{todos.map(todo => (
<TodoItem
key={todo.id}
todo={todo}
toggleCompleted={toggleCompleted}
deleteTodo={deleteTodo}
/>
))}
</ul>
);
};
export default TodoList;
En el archivo App.js se integra la lógica de la aplicación. Se utiliza el hook useState para mantener el estado de la lista de tareas. Además, se definen funciones que permiten agregar nuevas tareas, eliminar tareas existentes y alternar el estado "completado" de cada tarea.
// App.js
import React, { useState } from 'react';
import TodoInput from './components/TodoInput';
import TodoList from './components/TodoList';
import './App.css';
const App = () => {
const [todos, setTodos] = useState([]);
// Función para agregar una nueva tarea
const addTodo = (text) => {
const newTodo = {
id: Date.now(),
text: text,
completed: false,
};
setTodos([...todos, newTodo]);
};
// Función para eliminar una tarea
const deleteTodo = (id) => {
setTodos(todos.filter(todo => todo.id !== id));
};
// Función para alternar el estado completado de una tarea
const toggleCompleted = (id) => {
setTodos(
todos.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
)
);
};
return (
<div className="todo-app">
<h1>Mi Lista de Tareas</h1>
<TodoInput addTodo={addTodo} />
<TodoList todos={todos} toggleCompleted={toggleCompleted} deleteTodo={deleteTodo} />
</div>
);
};
export default App;
Es importante destacar cómo la aplicación utiliza el concepto de función pasada como prop para manejar eventos en componentes hijos, lo que permite que la gestión del estado sea centralizada en App.js.
Mejorar el diseño visual de tu aplicación puede aumentar la usabilidad y hacer que la experiencia del usuario sea más agradable. A continuación, se muestra un ejemplo de cómo se pueden utilizar estilos CSS en App.css para darle un acabado profesional a tu aplicación:
/* App.css */
.todo-app {
max-width: 500px;
margin: 40px auto;
padding: 20px;
border: 1px solid #ccc;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.todo-app h1 {
text-align: center;
}
form {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
input[type="text"] {
flex: 1;
padding: 10px;
font-size: 16px;
}
button {
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
}
ul {
list-style: none;
padding: 0;
}
li {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #ddd;
padding: 10px 0;
}
li div {
display: flex;
align-items: center;
}
li label {
margin-left: 10px;
font-size: 16px;
}
li button {
background-color: #f44336;
color: #fff;
border: none;
padding: 5px 10px;
}
Puedes ajustar estos estilos de acuerdo a las necesidades de tu proyecto o incluso incorporar frameworks CSS para una apariencia aún más sofisticada.
Una vez que hayas dominado la funcionalidad básica de la aplicación, existen muchas formas de ampliarla. Algunas ideas incluyen:
localStorage) del navegador para guardar la lista de tareas y recuperar la información en recargas.Cada uno de estos aspectos puede desarrollarse de forma incremental, lo que te permitirá aprender con prácticas reales de programación en React y mejorar la interacción con el usuario.
Mantener el código organizado es crucial para el mantenimiento y la escalabilidad de la aplicación. Algunas recomendaciones son:
Implementar una gestión adecuada de errores mejora la robustez de tu aplicación. Asegúrate de:
| Etapa | Descripción |
|---|---|
| Configuración | Instalación de Node.js, npm y creación de un nuevo proyecto con create-react-app. |
| Estructura de Componentes | Organización en componentes: Input para nuevas tareas, ítems individuales y lista para agruparlos. |
| Gestión del Estado | Uso de useState para mantener la lista de tareas y manejar actualizaciones mediante funciones específicas. |
| Implementación | Integración de la interfaz y la lógica en App.js, junto con la aplicación de estilos mediante CSS. |
| Extensión | Añadir nuevas funcionalidades como editar, filtrar, persistir datos y mejorar la interfaz de usuario. |
Estos pasos consolidan la base de un proyecto React, facilitando la adición de nuevas características a medida que tu experiencia crezca.