Here’s a concise JSX specification in 50 lines, blending syntax rules, semantics, behavior, and how JSX transpiles (mostly via Babel) to JavaScript. This aims to mirror what a minimal JSX RFC/spec might look like for language implementers or advanced users.
JSX Specification (in 50 lines)
- JSX is a syntactic sugar for
React.createElement(or equivalent). - JSX expressions must be wrapped in a single enclosing tag.
- JSX files typically use
.jsxor.tsxextensions. - JSX tags resemble HTML but map to JavaScript function calls.
- A JSX element:
<tag attr="value">children</tag>. - Elements are converted to
React.createElement(type, props, ...children). - Type is a string (
"div","span") or a React component identifier. - Tag names starting with a lowercase letter map to DOM elements.
- Tag names starting with uppercase letters map to React components.
- Self-closing tags are allowed:
<img />,<Component />. - JSX attributes map to object properties in
props. - Attribute values must be JavaScript expressions inside
{}. - String literals may be passed without
{}:<div title="Hi" />. - Boolean attributes:
<input disabled />⇒disabled: true. - The
classNameattribute is used instead ofclass. - The
htmlForattribute is used instead offor. - All other attributes follow camelCase naming (e.g.,
tabIndex). - Event handlers are camelCase:
onClick,onChange, etc. - Children can be strings, numbers, JSX, expressions, or arrays.
- Text content is automatically coerced to string.
- Comments inside JSX use
{/* like this */}. - Multiple children must be inside a wrapper element or
<>...</>. - Fragments can be used:
<>...</>(transpiles toReact.Fragment). - Conditional rendering:
{condition && <Component />}. - Ternary operators are supported:
{cond ? A : B}. - Loops must be in expressions:
{items.map(...)}. - You cannot use
if,for,whiledirectly in JSX. - Expressions are evaluated at render time.
- JSX supports spread attributes:
<Component {...props} />. - JSX does not support spreading children.
- Keys must be set when rendering arrays of elements.
- Keys help React optimize reconciliation during re-renders.
- JSX transforms into JavaScript before runtime (via Babel, TypeScript, etc.).
- A JSX tag like
<div id="main">Text</div>becomes: React.createElement("div", { id: "main" }, "Text").- If a component is used:
<MyComp name="x" />becomes: React.createElement(MyComp, { name: "x" }).- Nested JSX is recursively converted to nested
createElementcalls. - JSX supports inline functions:
<button onClick={() => foo()} />. - JSX may be nested in JavaScript logic outside of JSX itself.
- Attributes cannot contain statements — only expressions.
- Dangerous inner HTML must be explicitly set:
dangerouslySetInnerHTML. - Void elements (e.g.,
<input />,<img />) must be self-closing. - Comments outside of JSX use
//or/* ... */as usual. - JSX must be in scope with
Reactorjsxfactory function (e.g., with Babel). - The JSX pragma (e.g.,
/** @jsx h */) can change the transformation target. - TypeScript can use
@jsxImportSourceto select a custom JSX runtime. - In React 17+, the new JSX transform eliminates the need to
import React. - JSX is not HTML — it is closer to JavaScript syntax than browser DOM.
- JSX supports both static and dynamic rendering paths depending on usage.