JSX: Le Basi
Cos’è JSX?
JSX (JavaScript XML) è un’estensione sintattica di JavaScript che permette di scrivere strutture simili all’HTML direttamente nel codice JavaScript. Non è né una stringa né HTML puro: è una sintassi che viene trasformata in chiamate JavaScript durante la compilazione.
// JSX
const elemento = <h1>Ciao, mondo!</h1>;
// Viene trasformato dal compilatore in:
const elemento = React.createElement("h1", null, "Ciao, mondo!");
JSX è opzionale in React, ma la stragrande maggioranza degli sviluppatori lo utilizza perché rende il codice molto più leggibile e intuitivo.
Regole Fondamentali di JSX
Un Solo Elemento Root
Ogni espressione JSX deve avere un unico elemento radice. Non è possibile restituire elementi fratelli senza un contenitore.
// ERRORE: due elementi radice
function Componente() {
return (
<h1>Titolo</h1>
<p>Paragrafo</p>
);
}
// CORRETTO: un elemento radice
function Componente() {
return (
<div>
<h1>Titolo</h1>
<p>Paragrafo</p>
</div>
);
}
Tutti i Tag Devono Essere Chiusi
In JSX, ogni tag deve essere chiuso, compresi quelli che in HTML sono self-closing.
// HTML valido, JSX non valido
<img src="foto.jpg">
<br>
<input type="text">
// JSX valido
<img src="foto.jpg" />
<br />
<input type="text" />
CamelCase per gli Attributi
JSX usa il camelCase per gli attributi, non il kebab-case dell’HTML.
// HTML
<div class="container" tabindex="0" onclick="handleClick()">
// JSX
<div className="container" tabIndex={0} onClick={handleClick}>
Espressioni JavaScript in JSX
Le parentesi graffe {} permettono di inserire qualsiasi espressione JavaScript valida all’interno di JSX.
function Profilo() {
const nome = "Marco";
const eta = 28;
const oggi = new Date();
return (
<div>
<h1>{nome}</h1>
<p>Età: {eta}</p>
<p>Anno corrente: {oggi.getFullYear()}</p>
<p>Maggiorenne: {eta >= 18 ? "Sì" : "No"}</p>
<p>{`Ciao, mi chiamo ${nome} e ho ${eta} anni`}</p>
<p>Somma: {2 + 2}</p>
</div>
);
}
Cosa Si Può Inserire nelle Graffe
Le graffe accettano espressioni, non istruzioni. Ecco la differenza:
// VALIDO: espressioni
{nome} // Variabile
{getUtente()} // Chiamata a funzione
{a + b} // Operazione
{condizione ? "sì" : "no"} // Ternario
{array.map(item => ...)} // Metodo che ritorna un valore
// NON VALIDO: istruzioni
{if (condizione) { ... }} // if è un'istruzione
{for (let i = 0; ...) {}} // for è un'istruzione
{const x = 5} // dichiarazione
className vs class
In JSX si usa className al posto di class perché class è una parola riservata in JavaScript.
function Card() {
const isAttiva = true;
return (
<div className="card">
<h2 className="card-titolo">Titolo</h2>
{/* className dinamica */}
<div className={`badge ${isAttiva ? "attiva" : "inattiva"}`}>
Stato
</div>
</div>
);
}
Classi Dinamiche con Template Literal
function Pulsante({ variante, dimensione, disabilitato }) {
const classi = [
"btn",
`btn-${variante}`,
`btn-${dimensione}`,
disabilitato && "btn-disabled",
]
.filter(Boolean)
.join(" ");
return <button className={classi}>Click</button>;
}
Libreria clsx per Classi Condizionali
import clsx from "clsx";
function Pulsante({ variante, attivo, disabilitato }) {
return (
<button
className={clsx(
"btn",
`btn-${variante}`,
{ "btn-attivo": attivo, "btn-disabled": disabilitato }
)}
>
Click
</button>
);
}
Stili Inline
In JSX, la prop style accetta un oggetto JavaScript, non una stringa. Le proprietà CSS vanno scritte in camelCase.
function BoxColorato() {
const stile = {
backgroundColor: "#3b82f6",
color: "white",
padding: "16px",
borderRadius: "8px",
fontSize: "18px",
fontWeight: "bold",
};
return <div style={stile}>Box con stile inline</div>;
}
Stili Dinamici
function BarraProgresso({ percentuale }) {
return (
<div style={{ width: "100%", backgroundColor: "#e5e7eb", borderRadius: "4px" }}>
<div
style={{
width: `${percentuale}%`,
height: "20px",
backgroundColor: percentuale === 100 ? "#22c55e" : "#3b82f6",
borderRadius: "4px",
transition: "width 0.3s ease",
}}
/>
</div>
);
}
Quando Usare Stili Inline
Gli stili inline sono utili per valori veramente dinamici (calcolati a runtime). Per stili statici, preferisci CSS Modules, Tailwind o altri approcci.
Fragments
I Fragments permettono di raggruppare elementi senza aggiungere nodi extra al DOM.
import { Fragment } from "react";
// Sintassi completa
function ListaInfo() {
return (
<Fragment>
<h1>Titolo</h1>
<p>Descrizione</p>
</Fragment>
);
}
// Sintassi abbreviata (più comune)
function ListaInfo() {
return (
<>
<h1>Titolo</h1>
<p>Descrizione</p>
</>
);
}
Fragments con Key
Quando si renderizza una lista e serve la prop key, bisogna usare la sintassi completa <Fragment>.
import { Fragment } from "react";
function Glossario({ termini }) {
return (
<dl>
{termini.map((termine) => (
<Fragment key={termine.id}>
<dt>{termine.nome}</dt>
<dd>{termine.definizione}</dd>
</Fragment>
))}
</dl>
);
}
Commenti in JSX
Per inserire commenti dentro JSX, si usa la sintassi JavaScript racchiusa tra graffe.
function Componente() {
return (
<div>
{/* Questo è un commento in JSX */}
<h1>Titolo</h1>
{/*
Commento
su più righe
*/}
<p>Paragrafo</p>
{/* I commenti HTML <!-- --> NON funzionano in JSX */}
</div>
);
}
Attributi HTML Comuni in JSX
Ecco le differenze principali tra attributi HTML e JSX.
| HTML | JSX | Note |
|---|---|---|
class |
className |
class è riservata in JS |
for |
htmlFor |
for è riservata in JS |
tabindex |
tabIndex |
camelCase |
onclick |
onClick |
camelCase, funzione non stringa |
readonly |
readOnly |
camelCase |
maxlength |
maxLength |
camelCase |
style="color: red" |
style={{ color: "red" }} |
Oggetto, non stringa |
Rendering di Valori Speciali
JSX ignora alcuni valori durante il rendering, il che è utile per il rendering condizionale ma può causare bug imprevisti.
function EsempiRendering() {
return (
<div>
{/* Vengono renderizzati normalmente */}
{"stringa"} {/* "stringa" */}
{42} {/* "42" */}
{3.14} {/* "3.14" */}
{/* Vengono IGNORATI (non renderizzati) */}
{true} {/* nulla */}
{false} {/* nulla */}
{null} {/* nulla */}
{undefined} {/* nulla */}
{/* ATTENZIONE: 0 viene renderizzato! */}
{0} {/* "0" */}
{0 && <p>Testo</p>} {/* Mostra "0", non nulla! */}
{/* Soluzione: convertire a booleano */}
{!!0 && <p>Testo</p>} {/* nulla */}
{items.length > 0 && <p>Testo</p>} {/* nulla se array vuoto */}
</div>
);
}
JSX e Sicurezza
React escapa automaticamente i valori inseriti in JSX, proteggendo dall’XSS (Cross-Site Scripting).
function ComponenteSicuro() {
// Questo testo verrà mostrato letteralmente, non eseguito come HTML
const inputUtente = '<script>alert("hack")</script>';
return <div>{inputUtente}</div>;
// Renderizza: <script>alert("hack")</script> (come testo)
}
Se hai davvero bisogno di inserire HTML raw (da una fonte fidata), usa dangerouslySetInnerHTML.
function ArticoloBlog({ contenutoHtml }) {
// Usa con estrema cautela: solo con contenuto fidato e sanitizzato
return <div dangerouslySetInnerHTML={{ __html: contenutoHtml }} />;
}
Riepilogo
JSX è il cuore della sintassi React. Ricorda le regole fondamentali: un solo elemento radice, tag sempre chiusi, className al posto di class, stili come oggetti, e parentesi graffe per le espressioni JavaScript. I Fragments permettono di evitare wrapper inutili, e React protegge automaticamente dall’XSS. Padroneggiare JSX è il primo passo per scrivere componenti React efficaci.