Tutorial React TypeScript: Cómo Crear una App de Gestión de Tareas Paso a Paso
En este tutorial detallado, aprenderás a construir una aplicación sencilla de gestión de tareas utilizando React junto con TypeScript. Está especialmente dirigido a desarrolladores principiantes e intermedios que quieran mejorar sus habilidades en el desarrollo frontend moderno.
Te enseñaremos desde la configuración inicial del proyecto hasta la implementación de funcionalidades de agregar, listar, editar y eliminar tareas, manejando el estado con React Hooks y asegurando la persistencia de datos con Local Storage.
Índice
- 1. Configuración Inicial del Proyecto
- 2. Estructura del Proyecto y Tipos en TypeScript
- 3. Crear Componentes Funcionales Básicos
- 3.1 Componente para Agregar Tareas
- 3.2 Componente para Listar y Editar Tareas
- 3.3 Componente para Eliminar Tareas
- 4. Manejo del Estado con React Hooks
- 5. Persistencia con Local Storage
- 6. Código Completo y Explicación
- 7. Buenas Prácticas y Consejos Finales
- 8. Conclusión y Próximos Pasos
1. Configuración Inicial del Proyecto
Primero, configuraremos nuestro proyecto usando Vite con plantilla para React + TypeScript, pero también puedes hacerlo con Create React App.
Usando Vite (recomendado por rapidez)
Abre tu terminal y ejecuta:
1 2 3 4 5 |
npm create vite@latest react-tasks-app -- --template react-ts cd react-tasks-app npm install npm run dev |
Esto creará un proyecto React con TypeScript listo para empezar.
Alternativa: Create React App
1 2 3 4 |
npx create-react-app react-tasks-app --template typescript cd react-tasks-app npm start |
Ambas opciones te proporcionan una base para iniciar con React y TypeScript.
2. Estructura del Proyecto y Tipos en TypeScript
Vamos a definir qué tipo de datos manejará nuestra app.
Crea un archivo src/types.ts
para centralizar los tipos:
1 2 3 4 5 6 |
export interface Task { id: string; title: string; completed: boolean; } |
id
: cadena única para identificar la tarea.title
: texto descriptivo de la tarea.completed
: indica si la tarea está concluida.
Esta definición nos ayudará a tener un tipado estricto y claro.
3. Crear Componentes Funcionales Básicos
3.1 Componente para Agregar Tareas
Vamos a hacer un formulario que permita al usuario ingresar nuevas tareas.
src/components/AddTask.tsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
import React, { useState, FormEvent } from 'react'; interface AddTaskProps { onAdd: (title: string) => void; } const AddTask: React.FC<AddTaskProps> = ({ onAdd }) => { const [title, setTitle] = useState(''); const handleSubmit = (e: FormEvent) => { e.preventDefault(); if (title.trim().length === 0) return; onAdd(title.trim()); setTitle(''); }; return ( <form onSubmit={handleSubmit}> <input type="text" placeholder="Nueva tarea" value={title} onChange={e => setTitle(e.target.value)} required /> <button type="submit">Agregar</button> </form> ); }; export default AddTask; |
Explicación:
useState
controla el texto del input.- Al enviar el formulario, se llama a
onAdd
pasando el título validado. - Se limpia el campo.
3.2 Componente para Listar y Editar Tareas
Para listar las tareas y permitir edición de título y marcar completado, crearemos otro componente:
src/components/TaskList.tsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
import React from 'react'; import { Task } from '../types'; interface TaskListProps { tasks: Task[]; onToggle: (id: string) => void; onDelete: (id: string) => void; onEdit: (id: string, newTitle: string) => void; } const TaskList: React.FC<TaskListProps> = ({ tasks, onToggle, onDelete, onEdit }) => { const handleChangeTitle = ( e: React.ChangeEvent<HTMLInputElement>, task: Task ) => { onEdit(task.id, e.target.value); }; return ( <ul> {tasks.map((task) => ( <li key={task.id} style={{ display: 'flex', alignItems: 'center', gap: '8px' }}> <input type="checkbox" checked={task.completed} onChange={() => onToggle(task.id)} /> <input type="text" value={task.title} onChange={(e) => handleChangeTitle(e, task)} style={{ flexGrow: 1 }} /> <button onClick={() => onDelete(task.id)} aria-label={`Eliminar tarea ${task.title}`}>Eliminar</button> </li> ))} </ul> ); }; export default TaskList; |
Explicación:
- Por cada tarea se muestra un checkbox, un input para el título y un botón para eliminar.
- Cambiar el checkbox modifica el estado “completado”.
- Modificar el texto actualiza el título en tiempo real.
4. Manejo del Estado con React Hooks
Vamos a mantener las tareas en el estado del componente principal, y pasar las funciones necesarias a los hijos.
src/App.tsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
import React, { useState, useEffect } from 'react'; import { Task } from './types'; import AddTask from './components/AddTask'; import TaskList from './components/TaskList'; import { v4 as uuidv4 } from 'uuid'; const TASKS_STORAGE_KEY = 'react_tasks_app_tasks'; function App() { const [tasks, setTasks] = useState<Task[]>(() => { // Cargar tareas desde localStorage al inicio const stored = localStorage.getItem(TASKS_STORAGE_KEY); return stored ? JSON.parse(stored) : []; }); useEffect(() => { // Guardar tareas en localStorage cada vez que cambian localStorage.setItem(TASKS_STORAGE_KEY, JSON.stringify(tasks)); }, [tasks]); const addTask = (title: string) => { const newTask: Task = { id: uuidv4(), title, completed: false, }; setTasks((prev) => [...prev, newTask]); }; const toggleTask = (id: string) => { setTasks((prev) => prev.map((t) => (t.id === id ? { ...t, completed: !t.completed } : t)) ); }; const deleteTask = (id: string) => { setTasks((prev) => prev.filter((t) => t.id !== id)); }; const editTask = (id: string, newTitle: string) => { setTasks((prev) => prev.map((t) => (t.id === id ? { ...t, title: newTitle } : t)) ); }; return ( <main style={{ maxWidth: 600, margin: '2rem auto', padding: '0 1rem' }}> <h1>Gestión de Tareas con React y TypeScript</h1> <AddTask onAdd={addTask} /> <TaskList tasks={tasks} onToggle={toggleTask} onDelete={deleteTask} onEdit={editTask} /> </main> ); } export default App; |
Explicación:
- Usamos
useState
para controlar la lista de tareas. useEffect
sincroniza el estado conlocalStorage
para persistencia.- Funciones para agregar, alternar completado, eliminar y editar tareas actualizan el estado.
- Usamos
uuid
para generar IDs únicas al agregar tareas.
5. Persistencia con Local Storage
Se maneja dentro de los hooks del componente principal para conservar las tareas al recargar:
1 2 3 4 5 6 7 8 9 |
const [tasks, setTasks] = useState<Task[]>(() => { const stored = localStorage.getItem(TASKS_STORAGE_KEY); return stored ? JSON.parse(stored) : []; }); useEffect(() => { localStorage.setItem(TASKS_STORAGE_KEY, JSON.stringify(tasks)); }, [tasks]); |
- Cuando la app inicia, carga las tareas guardadas.
- Cada cambio se guarda automáticamente.
Esto garantiza que el usuario no pierda la información por refrescos o cierres del navegador.
6. Código Completo y Explicación
Paquete de dependencias adicional:
Para generar IDs únicas:
1 2 3 |
npm install uuid npm install -D @types/uuid |
Archivos clave:
src/types.ts
src/components/AddTask.tsx
src/components/TaskList.tsx
src/App.tsx
Puedes copiar y pegar los códigos antes mencionados para tener la app funcional.
7. Buenas Prácticas y Consejos Finales
- Uso consistente de tipado estricto te ayuda a prevenir errores.
- Divide el UI en componentes pequeños y reusables.
- Maneja el estado principal en el componente más alto necesario para evitar props innecesarios.
- Asegúrate de validar entradas del usuario.
- Utiliza
localStorage
para persistencia sencilla, pero para apps más grandes considera bases de datos o almacenamiento en la nube. - Mantén tu código limpio, con nombres descriptivos y modularizado.
8. Conclusión y Próximos Pasos
¡Felicidades! Ahora tienes una aplicación de gestión de tareas funcional creada con React y TypeScript, con tipado estricto, manejo de estado moderno y persistencia de datos.
Este proyecto es una base perfecta para seguir aprendiendo:
- Añadir filtros para mostrar tareas completadas o pendientes.
- Implementar autenticación para usuarios.
- Mejorar el diseño con CSS o frameworks como Tailwind CSS.
- Usar React Context o Redux para manejo de estado más complejo.
Si te ha gustado este tutorial React TypeScript, no dudes en compartirlo y suscribirte para más guías y proyectos frontend.
¡Manos a la obra y felices desarrollos!
Palabras clave: tutorial React TypeScript, crear app tareas React, gestión de tareas con React y TypeScript, proyecto React para principiantes