💻 Exemplos: Capítulo 05: Memoização e Otimização de Performance (useMemo, useCallback)
Especialização Frontend com React & TypeScript • Demonstrações Práticas Executáveis
🎯 Contexto e Objetivo Prático
Otimização de computação intensiva com useMemo e estabilização de referências de funções com useCallback para componentes memoizados.
💻 Código Fonte React 19 (TSX)
// ExpensiveListFilter.tsx
import React, { useState, useMemo, useCallback } from "react";
interface ProductRecord {
id: string;
sku: string;
price: number;
category: "hardware" | "software" | "cloud";
}
// Componente Filho Memoizado para evitar re-render inútil
const ProductRow = React.memo(function ProductRow({
product,
onSelect
}: {
product: ProductRecord;
onSelect: (sku: string) => void;
}) {
return (
<tr className="border-b hover:bg-slate-50">
<td className="p-2 font-mono text-xs">{product.sku}</td>
<td className="p-2 text-sm">{product.category}</td>
<td className="p-2 text-sm font-semibold">R$ {product.price.toFixed(2)}</td>
<td className="p-2">
<button
onClick={() => onSelect(product.sku)}
className="text-xs bg-slate-100 hover:bg-slate-200 px-2 py-1 rounded"
>
Selecionar
</button>
</td>
</tr>
);
});
export function ProductCatalog({ initialProducts }: { initialProducts: ProductRecord[] }) {
const [filterCategory, setFilterCategory] = useState<string>("all");
const [selectedSku, setSelectedSku] = useState<string | null>(null);
// 1. useMemo: Recalcula o filtro apenas se a categoria ou lista mudarem
const filteredProducts = useMemo(() => {
if (filterCategory === "all") return initialProducts;
return initialProducts.filter(p => p.category === filterCategory);
}, [initialProducts, filterCategory]);
// 2. useCallback: Mantém a mesma referência de função para não invalidar o React.memo
const handleSelectProduct = useCallback((sku: string) => {
setSelectedSku(sku);
console.log(`SKU selecionado: ${sku}`);
}, []);
return (
<div className="p-4">
<div className="mb-4 flex items-center gap-4">
<select
value={filterCategory}
onChange={e => setFilterCategory(e.target.value)}
className="border p-2 rounded text-sm"
>
<option value="all">Todas as Categorias</option>
<option value="hardware">Hardware</option>
<option value="cloud">Cloud</option>
</select>
<span className="text-sm text-slate-500">
Exibindo {filteredProducts.length} de {initialProducts.length} registros
</span>
</div>
<table className="w-full text-left border-collapse">
<tbody>
{filteredProducts.map(prod => (
<ProductRow key={prod.id} product={prod} onSelect={handleSelectProduct} />
))}
</tbody>
</table>
</div>
);
}
🖥️ Saída de Renderização Visual e Comportamento
[Catálogo Otimizado]
Filtro: Cloud | Exibindo 2 de 5 registros
SKU: CLD-AWS-01 | Preço: R$ 450,00 [Selecionar]
SKU: CLD-GCP-02 | Preço: R$ 890,00 [Selecionar]