JSX
The syntax that lets you write markup inside JavaScript, and the handful of rules that differ from HTML.
JSX is a syntax, not a template language
JSX looks like HTML sitting inside JavaScript. It is neither string templating nor HTML — it is syntax sugar that a build tool converts into function calls.
const heading = <h1 className="title">Hello</h1>;becomes, roughly:
const heading = React.createElement(
"h1",
{ className: "title" },
"Hello"
);Because JSX is just JavaScript, an element is an ordinary value. You can store it in a variable, put it in an array, return it from a function, or pass it as an argument.
Embedding expressions
Curly braces switch from markup back to JavaScript. Anything that evaluates to a value can go inside them.
const user = { first: "Ada", last: "Lovelace" };
function Profile() {
return (
<div>
<h1>{user.first + " " + user.last}</h1>
<p>Name length: {user.first.length}</p>
<p>Today: {new Date().toDateString()}</p>
</div>
);
}Braces take expressions, not statements. An if block or a for loop will not work inside them; a ternary or a call to map will.
One root element
An expression produces one value, so JSX must return a single element. Wrapping in a div works but adds a node you may not want.
// Not valid — two siblings at the top level
return (
<h1>Title</h1>
<p>Body</p>
);
// Valid — a fragment, which renders nothing itself
return (
<>
<h1>Title</h1>
<p>Body</p>
</>
);The empty tags are a fragment. Use the longer form React.Fragment when you need to give it a key inside a list.
Attributes that differ from HTML
JSX attribute names follow JavaScript's DOM property names, which are camelCase, and avoid reserved words.
- class becomes className
- for becomes htmlFor
- onclick becomes onClick, onchange becomes onChange
- tabindex becomes tabIndex
- data- and aria- attributes keep their dashes
<label htmlFor="email" className="field-label">Email</label>
<input id="email" type="email" aria-required="true" />Closing every tag
HTML tolerates unclosed tags. JSX does not. Void elements such as img, input, and br must be self-closed.
<img src="/logo.svg" alt="Logo" />
<input type="text" />
<br />Inline styles are objects
The style attribute takes an object, not a string. Property names are camelCase and numeric values default to pixels.
const box = {
backgroundColor: "#e8f4f8",
paddingTop: 12,
borderRadius: 8,
};
return <div style={box}>Styled</div>;The double braces you often see — style={{ color: "red" }} — are not special syntax. The outer pair enters JavaScript, the inner pair is an object literal.
Comments
return (
<div>
{/* This is a comment inside JSX */}
<p>Visible</p>
</div>
);JSX escapes values for you
Anything you interpolate is inserted as text, so a string containing markup shows up as characters rather than being parsed as HTML. This makes cross-site scripting hard to introduce by accident.
const input = "<script>alert(1)</script>";
// Renders the characters, does not run anything
return <p>{input}</p>;