Strategie e tecniche per migliorare le performance delle tue applicazioni React.
Le performance sono uno degli aspetti più critici di qualsiasi applicazione web moderna. In React, un rendering non ottimizzato può trasformare un'interfaccia fluida in un'esperienza frustrante, specialmente su dispositivi a bassa potenza. In questa guida esploriamo le tecniche fondamentali per mantenere la tua app React veloce e reattiva.
Prima di ottimizzare, è essenziale capire quando React decide di ri-renderizzare un componente:
Quest'ultimo punto è la causa più comune di render non necessari.
I due hook più usati per evitare ricalcoli costosi:
// Senza ottimizzazione - recalcola ad ogni render
function ProductList({ products, filter }) {
const filtered = products.filter(p => p.category === filter);
return filtered.map(p => <Product key={p.id} {...p} />);
}
// Con useMemo - ricalcola solo quando cambiano le dipendenze
function ProductList({ products, filter }) {
const filtered = useMemo(
() => products.filter(p => p.category === filter),
[products, filter]
);
return filtered.map(p => <Product key={p.id} {...p} />);
}
useCallback è l'equivalente per le funzioni:
// La funzione viene ricreata solo se userId cambia
const handleEdit = useCallback((productId) => {
editProduct(userId, productId);
}, [userId]);
Wrappa un componente con React.memo per saltare il re-render se le props non cambiano:
const Product = React.memo(function Product({ name, price, onAdd }) {
console.log("rendering:", name);
return (
<div>
<h3>{name}</h3>
<span>{price}€</span>
<button onClick={onAdd}>Aggiungi</button>
</div>
);
});
Attenzione:
React.memousa un confronto superficiale (shallow equality). Se passi oggetti o array come props, considera una funzione di comparazione personalizzata.
Renderizzare migliaia di elementi nel DOM è devastante per le performance. Usa la virtualizzazione per renderizzare solo gli elementi visibili:
import { FixedSizeList } from "react-window";
function VirtualList({ items }) {
const Row = ({ index, style }) => (
<div style={style}>
<ProductCard product={items[index]} />
</div>
);
return (
<FixedSizeList
height={600}
itemCount={items.length}
itemSize={80}
width="100%"
>
{Row}
</FixedSizeList>
);
}
Carica i componenti pesanti solo quando servono:
import { lazy, Suspense } from "react";
const ChartDashboard = lazy(() => import("./ChartDashboard"));
const AdminPanel = lazy(() => import("./AdminPanel"));
function App() {
return (
<Suspense fallback={<Spinner />}>
<Routes>
<Route path="/charts" element={<ChartDashboard />} />
<Route path="/admin" element={<AdminPanel />} />
</Routes>
</Suspense>
);
}
React DevTools offre un profiler integrato per identificare i colli di bottiglia:
key in liste dinamicheL'ottimizzazione in React non è una singola tecnica, ma un approccio sistematico: prima misura (DevTools Profiler), poi ottimizza. Applicare useMemo e useCallback ovunque senza misurare può addirittura peggiorare le performance per via del costo degli hook stessi.
Identifica i bottleneck reali, ottimizza dove conta davvero, e la tua app React velerà via.