JSX è un'estensione della sintassi di JavaScript che ti permette di scrivere markup simile all'HTML dentro il tuo codice. I componenti React restituiscono JSX per descrivere cosa deve apparire sullo schermo, e uno strumento di build lo compila in normali chiamate di funzione JavaScript. Sembra HTML, ma alcune regole sono diverse, e le parentesi graffe ti permettono di inserire qualsiasi valore JavaScript nel markup.
Tutto ciò che sta dentro {} è JavaScript: una proprietà, una chiamata di metodo, persino map che trasforma un array in elementi di lista. Aggiungi 'design' all'array skills e sia il conteggio sia la lista si aggiornano.
Le regole di JSX
Restituisci un solo elemento radice
Un componente restituisce un solo valore, quindi il suo JSX ha bisogno di un solo genitore. Due elementi fratelli al livello più alto sono un errore di sintassi. Quando non vuoi un <div> in più nella pagina, racchiudili in un fragment, <>...</>:
// Error: Adjacent JSX elements must be wrapped in an enclosing tag
return (
<h1>Title</h1>
<p>Text</p>
);
// OK: a fragment groups them without adding a DOM element
return (
<>
<h1>Title</h1>
<p>Text</p>
</>
);
Quando ti serve una key sul gruppo, usa la forma lunga <Fragment key={id}>; vedi fragment.
Chiudi ogni tag
L'HTML ti permette di lasciare aperti alcuni tag. JSX no. Gli elementi senza figli si chiudono da soli con />: <img />, <br />, <input /> e i tuoi componenti come <Avatar />.
Usa className, htmlFor e attributi in camelCase
Gli attributi JSX diventano chiavi di un oggetto JavaScript, quindi seguono le convenzioni di nomi di JavaScript. class e for sono parole riservate in JavaScript, ed è per questo che JSX usa className e htmlFor. Gli attributi composti da più parole e tutti i gestori di eventi sono in camelCase: tabIndex, maxLength, autoFocus, onClick, onChange. Due eccezioni mantengono i trattini: gli attributi aria-* e data-* si scrivono esattamente come in HTML.
Cambia className="field" in class="field". L'etichetta mantiene il suo stile, perché React imposta comunque l'attributo, ma una build di sviluppo registra "Invalid DOM property class. Did you mean className?". L'anteprima gira come una build di produzione, quindi qui non vedrai quell'avviso; usa className. Un attributo stringa usa le virgolette (type="email"); qualsiasi altro valore usa le graffe (maxLength={40}, disabled={false}).
Le parentesi graffe accettano espressioni, non istruzioni
Dentro {} puoi scrivere qualunque cosa produca un valore: una variabile, un'operazione aritmetica, una chiamata di funzione, un ternario, &&, un template literal. Istruzioni come if, for e const non producono un valore, quindi non possono stare lì. Fai il lavoro prima del return, oppure usa una forma a espressione:
Guarda bene prima di cliccare: la pagina mostra uno 0 di troppo. count && <p>...</p> vale 0 quando il conteggio è zero, e React renderizza i numeri, anche lo zero. Cambialo in count > 0 && <p>You have mail.</p> e lo 0 sparisce. false, null, undefined e true non renderizzano nulla, ed è per questo che un booleano a sinistra di && è sicuro. La pagina sul rendering condizionale tratta questi schemi.
Gli stili inline usano un oggetto
L'attributo style accetta un oggetto JavaScript, non una stringa CSS. Da qui l'aspetto a "doppie graffe": la coppia esterna significa "qui c'è JavaScript", quella interna è il letterale dell'oggetto. I nomi delle proprietà sono in camelCase (backgroundColor, fontSize), e un numero semplice significa pixel per la maggior parte delle proprietà di dimensione.
Poiché lo stile è un oggetto, può essere calcolato dallo stato come qualsiasi altro valore. Prova a cambiare fontSize: big ? 24 : 16 in fontSize: big ? '2em' : '1em': le stringhe vengono passate così come sono, con la loro unità.
Commenti
Un commento dentro JSX va tra parentesi graffe: {/* questo è un commento */}. I commenti HTML (<!-- -->) sono un errore di sintassi. Fuori dal markup, nel corpo della funzione, i normali commenti // funzionano come sempre.
return (
<div>
{/* The header is hidden on small screens */}
<Header />
</div>
);
Convertire HTML in JSX
Incollare HTML in un componente è un primo passo comune, e gran parte funziona. Queste sono le modifiche che di solito devi fare:
classdiventaclassName, efordiventahtmlFor.- I tag vuoti si chiudono da soli:
<br>diventa<br />,<img src="a.png">diventa<img src="a.png" />. style="color: red; font-size: 14px"diventastyle={{ color: 'red', fontSize: 14 }}.- Gli attributi di evento accettano una funzione, non una stringa:
onclick="save()"diventaonClick={save}. - I nomi degli attributi diventano camelCase:
tabindexdiventatabIndex, e lostroke-widthdi SVG diventastrokeWidth. <!-- comments -->diventano{/* comments */}.- Più elementi al livello più alto hanno bisogno di un solo genitore o di un fragment.
I convertitori online da HTML a JSX fanno questi passaggi per te, ma conoscerli rende facili da leggere i messaggi di errore quando te ne sfugge uno.
In cosa viene compilato JSX
I browser non possono eseguire JSX. Un compilatore (come Babel, SWC o Oxc, che Vite e i framework eseguono per te) trasforma ogni tag in una chiamata di funzione da react/jsx-runtime:
// What you write
const element = <h1 className="title">Hello, {name}</h1>;
const button = <Button size="small">OK</Button>;
// What the compiler produces (roughly)
import { jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime';
const element = _jsxs('h1', { className: 'title', children: ['Hello, ', name] });
const button = _jsx(Button, { size: 'small', children: 'OK' });
Un tag minuscolo diventa una stringa ('h1', un elemento HTML), uno con l'iniziale maiuscola diventa un riferimento alla tua funzione (Button), gli attributi diventano l'oggetto props e il contenuto diventa children. Le configurazioni più vecchie compilavano invece in React.createElement(type, props, ...children), ed è per questo che i vecchi file iniziano con import React from 'react' anche quando non nominano mai React. La chiamata restituisce un semplice oggetto chiamato elemento React. Puoi stamparne uno nella console:
La console mostra che heading è solo un dato: un tipo 'h3' e un oggetto props. È anche per questo che JSX può essere salvato in variabili, passato a funzioni e restituito da esse.
JSX fa l'escape del testo per te
Qualsiasi stringa che metti tra le graffe viene renderizzata come testo, mai come HTML. Se un utente scrive <img src=x onerror=alert(1)> in una casella di commento, React mostra quei caratteri sullo schermo invece di creare un tag immagine. Questo blocca di default la forma più comune di cross site scripting (XSS).
Il primo paragrafo stampa i tag come semplici caratteri. Il secondo usa dangerouslySetInnerHTML, che salta l'escape e inserisce la stringa come vero HTML, quindi "our own" è in grassetto. Il nome lungo è un avvertimento: passa solo HTML che hai prodotto tu stesso o che hai ripulito con un sanitizer come DOMPurify. Passarci l'input degli utenti riapre la falla XSS che JSX aveva chiuso.
Domande frequenti
Cosa significa JSX?
JSX sta per JavaScript XML. È un'estensione della sintassi che ti permette di scrivere markup simile all'HTML dentro il codice JavaScript.
JSX è HTML?
No. JSX sembra HTML ma viene compilato in chiamate di funzione JavaScript che creano elementi React. Per questo usa className al posto di class, nomi di attributi in camelCase e richiede che ogni tag sia chiuso.
Posso usare React senza JSX?
Sì. JSX è facoltativo: puoi chiamare direttamente createElement('h1', { className: 'title' }, 'Hello') da react. Quasi tutti i progetti React usano JSX perché il markup annidato è molto più facile da leggere.
Perché non posso usare un if dentro JSX?
Le parentesi graffe in JSX accettano espressioni, cioè cose che producono un valore, e if è un'istruzione. Usa un operatore ternario (cond ? a : b), &&, oppure calcola il valore in una variabile prima del return.
Come scrivo un commento in JSX?
Racchiudi un commento JavaScript tra parentesi graffe: {/* così */}. I commenti HTML (<!-- -->) sono un errore di sintassi in JSX.