💻 Exemplos: Capítulo 03: Gerenciamento de Estado com useState e Imutabilidade
Especialização Frontend com React & TypeScript • Demonstrações Práticas Executáveis
🎯 Contexto e Objetivo Prático
Gerenciamento de coleções com useState, atualizações funcionais imutáveis com .map e .filter, e tipagem estrita de payloads.
💻 Código Fonte React 19 (TSX)
// TaskManager.tsx
import React, { useState } from "react";
export interface TaskItem {
id: string;
title: string;
isCompleted: boolean;
priority: "baixa" | "media" | "alta";
}
export function TaskManager() {
const [tasks, setTasks] = useState<TaskItem[]>([
{ id: "task-1", title: "Configurar tsconfig com strict: true", isCompleted: true, priority: "alta" },
{ id: "task-2", title: "Implementar validação com Zod", isCompleted: false, priority: "media" }
]);
const [newTaskTitle, setNewTaskTitle] = useState("");
const handleAddTask = (e: React.FormEvent) => {
e.preventDefault();
if (!newTaskTitle.trim()) return;
const newTask: TaskItem = {
id: `task-${Date.now()}`,
title: newTaskTitle.trim(),
isCompleted: false,
priority: "media"
};
// Imutabilidade estrita: novo array sem mutar o anterior
setTasks(prev => [...prev, newTask]);
setNewTaskTitle("");
};
const handleToggleTask = (id: string) => {
setTasks(prev =>
prev.map(task => (task.id === id ? { ...task, isCompleted: !task.isCompleted } : task))
);
};
const handleDeleteTask = (id: string) => {
setTasks(prev => prev.filter(task => task.id !== id));
};
return (
<section className="max-w-md mx-auto p-4 bg-slate-50 rounded-xl">
<h2 className="text-lg font-bold text-slate-800 mb-4">Gerenciador de Tarefas</h2>
<form onSubmit={handleAddTask} className="flex gap-2 mb-4">
<input
type="text"
value={newTaskTitle}
onChange={e => setNewTaskTitle(e.target.value)}
placeholder="Nova tarefa..."
className="flex-1 px-3 py-2 border rounded-md text-sm"
/>
<button type="submit" className="px-4 py-2 bg-blue-600 text-white rounded-md text-sm">
Adicionar
</button>
</form>
<ul className="space-y-2">
{tasks.map(task => (
<li key={task.id} className="flex items-center justify-between p-2 bg-white rounded border">
<label className="flex items-center gap-2 text-sm cursor-pointer">
<input
type="checkbox"
checked={task.isCompleted}
onChange={() => handleToggleTask(task.id)}
/>
<span className={task.isCompleted ? "line-through text-slate-400" : "text-slate-700"}>
{task.title}
</span>
</label>
<button
onClick={() => handleDeleteTask(task.id)}
className="text-xs text-red-500 hover:text-red-700"
>
Excluir
</button>
</li>
))}
</ul>
</section>
);
}
🖥️ Saída de Renderização Visual e Comportamento
[Lista Interativa de Tarefas]
[x] Configurar tsconfig com strict: true [Excluir]
[ ] Implementar validação com Zod [Excluir]
Total de tarefas no estado: 2 (1 concluída)