Hai già scritto JavaScript, ma quando apri un file .jsx ti sembra di leggere un'altra lingua. Il componente non si aggiorna, le props non arrivano, lo state non si comporta come pensavi. Non sei il primo, e non è colpa tua. React ha una logica diversa dal jQuery o dal vanilla JS a cui sei abituato. Noi di Meteora Web costruiamo applicazioni con React da anni — piattaforme proprietarie, dashboard, e-commerce — e abbiamo visto centinaia di sviluppatori (e noi stessi) inciampare sugli stessi punti. Questa guida ti dà le fondamenta per smettere di combattere React e iniziare a usarlo come un professionista.
JSX: Non è HTML, è Zucchero Sintattico
JSX sembra HTML, ma non lo è. Viene compilato da Babel in chiamate React.createElement. Questo significa che ogni attributo HTML ha un nome diverso in JSX: class diventa className, for diventa htmlFor, tabindex diventa tabIndex, e via dicendo. Lo stile inline non è una stringa ma un oggetto JavaScript con proprietà in camelCase.
// Sbagliato
<div class="container" style="color: red;">
Ciao
</div>
// Corretto
<div className="container" style={{ color: 'red' }}>
Ciao
</div>
Errore comune: scrivere attributi HTML nativi e poi chiedersi perché non funzionano. JSX non è un template engine — è JavaScript che produce elementi React. Ogni espressione dentro le graffe {} viene valutata come JavaScript. Per questo puoi metterci funzioni, ternari, array.map, ma non if o for (vanno usati al di fuori del return o con espressioni).
Cosa fare adesso: Apri un componente vuoto e scrivi un div con className e style oggetto. Poi prova a inserire una variabile dentro {}. Se il colore del testo cambia, hai capito il meccanismo.
Componenti: Funzioni, Non Classi
Nel 2025 i componenti classe sono legacy. Non c'è più motivo di usarli: gli Hooks (da React 16.8) coprono tutto. Un componente React è una funzione che accetta props e restituisce JSX. Punto.
function Card({ title, children }) {
return (
<div className="card">
<h2>{title}</h2>
<div className="card-body">{children}</div>
</div>
);
}
Come vedi, il componente è puro: dati in ingresso (props), JSX in uscita. Niente this, niente render(), niente state manager preistorico. Less is more. Puoi esportarlo come default o nominato, a seconda delle necessità del progetto.
Errore comune: dimenticare il return implicito con le frecce, o chiudere tag che dovrebbero essere self-closing (es. <img />). React richiede JSX valido, altrimenti bella roba.
Cosa fare adesso: Trasforma un componente classe che hai scritto in passato in una funzione. Se non ne hai, crea un Welcome che prende un prop name e stampa "Ciao, {name}!".
Props: Il Flusso Discendente dei Dati
Le props sono i parametri di una funzione: arrivano dall'esterno e non si modificano. Un componente figlio non deve mai riassegnare props.nome. Le props sono read-only. Questo è il principio del flusso unidirezionale: i dati scendono dal genitore al figlio.
function Avatar({ src, alt, size = 50 }) {
return <img src={src} alt={alt} width={size} height={size} />;
}
// Uso
<Avatar src="https://example.com/me.jpg" alt="Mia foto" />
Nota: size ha un valore di default (50). Questo è il modo moderno di gestire i valori opzionali, al posto delle deprecated defaultProps. Se usi TypeScript, meglio definire un'interfaccia. Parliamone tra poco.
Errore comune: modificare le props nel figlio. Se hai bisogno di dati locali derivati, usa useState o useMemo. Non scrivere props.size = 100 — React non lo permette e ti dà errore in console.
Cosa fare adesso: Crea un componente genitore che passa un array di oggetti a un componente figlio, e il figlio li renderizza in una lista con .map() e key. Usa children per passare del markup arbitrario.
State: La Memoria Locale del Componente
Lo state è la differenza fondamentale: mentre le props arrivano da fuori e sono immutabili, lo state è gestito internamente e può cambiare. Il gancio useState restituisce un array con due elementi: il valore corrente e una funzione per aggiornarlo.
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Hai cliccato {count} volte</p>
<button onClick={() => setCount(count + 1)}>
+1
</button>
</div>
);
}
Attenzione: setCount è asincrono. Se hai bisogno del valore precedente per calcolare il nuovo, usa la forma funzionale: setCount(prev => prev + 1). Questo evita bug quando lo state viene aggiornato più volte in rapida successione.
Errore comune: mettere tutto lo state nello stesso componente, o al contrario frammentarlo troppo. Regola pratica: se un dato può essere derivato da props o da altro state, non metterlo in state. Calcolalo al volo con useMemo. Se due componenti fratelli condividono lo stesso state, sollevalo al genitore comune (lifting state up).
Cosa fare adesso: Aggiungi un pulsante "-1" al counter e usa la forma funzionale per assicurarti che funzioni anche se clicchi velocemente. Poi crea un form con due campi controllati (ogni campo ha il suo useState) e un bottone di submit.
Re-render e Ottimizzazione
React rirenderizza un componente ogni volta che cambiano le sue props o il suo state. Di default, tutto l'albero discendente viene rirenderizzato. Questo è il comportamento voluto nella maggior parte dei casi, ma in componenti pesanti può causare rallentamenti.
Soluzioni:
- React.memo: avvolgi il componente per evitare re-render se le props non sono cambiate (shallow comparison).
- useMemo: memorizza il risultato di un calcolo costoso fino a che le dipendenze non cambiano.
- useCallback: evita di ricreare funzioni ad ogni render, utile quando le passi come props a componenti memoizzati.
const MemoizedList = React.memo(function List({ items }) {
console.log('Renderizzo lista');
return items.map(item => <p key={item.id}>{item.name}</p>);
});
Quando usare queste ottimizzazioni? Solo quando misuri un problema reale. Non anticipare — React è già veloce. Noi l'abbiamo visto su decine di progetti: una profilazione con React DevTools ti dice dove intervenire.
TypeScript + React: La Combinazione Vincente
Se non usi ancora TypeScript, questo è il momento. Tipizzare props e state ti fa risparmiare ore di debug. Con un file .tsx puoi definire interfacce chiare:
interface CardProps {
title: string;
children: React.ReactNode;
onClose?: () => void; // opzionale
}
function Card({ title, children, onClose }: CardProps) {
return (
<div className="card">
<h2>{title}</h2>
{onClose && <button onClick={onClose}>X</button>}
<div>{children}</div>
</div>
);
}
In questo modo, se passi una prop sbagliata o dimentichi una prop obbligatoria, TypeScript ti avvisa in fase di compilazione, non a runtime. Noi di Meteora Web usiamo TypeScript in ogni progetto React da anni. Il costo iniziale è bassissimo, il guadagno è enorme.
Cosa fare adesso: Installa TypeScript in un progetto React esistente (o creane uno nuovo con Vite: npm create vite@latest e scegli React+TS). Converti uno dei componenti che hai scritto aggiungendo le interfacce per props e state.
In Sintesi — Cosa Fare Adesso
- Smetti di pensare a JSX come HTML. Ogni attributo ha un nome JavaScript, e le espressioni vanno dentro
{}. - Usa sempre componenti funzione e hooks. Le classi sono storia. Impara
useStateeuseEffecte sarai coperto per l'80% dei casi. - Props scendono, state è locale. Non modificare le props. Solleva lo state quando serve a più componenti.
- Tipizza con TypeScript. Non rimandare: ogni ora spesa su un bug di tipo è tempo perso.
- Profitta di React DevTools. Installali subito. Ti mostrano state, props e re-render in tempo reale.
Hai le basi per costruire applicazioni React solide e manutenibili. Noi li abbiamo usati per piattaforme come un sistema di pubblicazione social automatica e dashboard analitiche — e funzionano. Se vuoi andare più a fondo, dai un'occhiata a come integriamo React con backend Laravel per applicazioni full-stack. Il resto è pratica.
Sponsored Protocol