JSX: Syntax, Expressions, and Comments
JSX (JavaScript XML) is a syntax extension for JavaScript that allows you to write HTML-like code inside your JavaScript files. It is used by React to describe what the UI should look like. JSX is not HTML – it's a syntactic sugar that gets compiled to React.createElement() calls.
JSX stands for JavaScript XML. It allows you to write markup directly in your JavaScript code, combining the power of JavaScript with a declarative UI description.
Why JSX?
- Familiar syntax – resembles HTML, making it easy to learn.
- Declarative – you describe what the UI should look like.
- Full JavaScript power – you can embed expressions and logic.
- React‑specific features – supports props, children, and event handlers.
// Without JSX (using React.createElement)
const element = React.createElement('h1', { className: 'greeting' }, 'Hello, world!');
// With JSX (much more readable)
const element = <h1 className="greeting">Hello, world!</h1>;
JSX is optional but highly recommended. Most React developers prefer JSX for its readability and expressiveness.
JSX looks like HTML but has some important differences.
Elements and Tags
JSX elements can be HTML tags or React components.
// HTML tags (lowercase)
const div = <div>Hello</div>;
const button = <button>Click</button>;
// React components (capitalized)
const MyComponent = () => <p>Hi</p>;
const element = <MyComponent />;
Self‑Closing Tags
Tags without children must be self‑closed:
// Correct
const img = <img src="photo.jpg" alt="Profile" />;
const input = <input type="text" />;
// Incorrect – will cause an error
const img = <img src="photo.jpg" alt="Profile">;
Fragments
To return multiple elements without an extra wrapper, use <></> or <Fragment>:
return (
<>
<h1>Title</h1>
<p>Paragraph</p>
</>
);
Why Fragments?
Fragments avoid unnecessary <div> wrappers, keeping the DOM clean and semantic.
JSX attributes use camelCase instead of HTML's kebab‑case for some attributes.
Common Attribute Differences
| HTML | JSX | Reason |
|---|---|---|
class |
className |
class is a reserved word in JavaScript |
for (labels) |
htmlFor |
for is a reserved word |
tabindex |
tabIndex |
camelCase convention |
onclick |
onClick |
camelCase for event handlers |
style="color: red;" |
style={{ color: 'red' }} |
Style is an object |
// HTML attribute (kebab-case)
<label for="name">Name</label>
<div class="container" tabindex="0">...</div>
// JSX (camelCase)
<label htmlFor="name">Name</label>
<div className="container" tabIndex="0">...</div>
Boolean Attributes
In JSX, you can omit the value for boolean attributes, defaulting to true:
// Both are equivalent
<input disabled={true} />
<input disabled />
JSX allows you to embed any JavaScript expression inside curly braces {}.
Basic Expression
const name = 'Alice';
const element = <h1>Hello, {name}!</h1>; // "Hello, Alice!"
Any Valid Expression
You can put function calls, arithmetic, ternary operators, etc.
const user = { firstName: 'John', lastName: 'Doe' };
const element = (
<div>
<p>Full name: {user.firstName + ' ' + user.lastName}</p>
<p>Age: {2026 - 1990}</p>
<p>Status: {isLoggedIn ? 'Online' : 'Offline'}</p>
<p>Total: {items.reduce((sum, item) => sum + item.price, 0)}</p>
</div>
);
Rendering Lists with map()
const items = ['Apple', 'Banana', 'Orange'];
const list = (
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
Conditional Rendering
Use && or ternary operators:
const isLoggedIn = true;
return (
<div>
{isLoggedIn && <p>Welcome back!</p>}
{isLoggedIn ? <p>Logged in</p> : <p>Please log in</p>}
</div>
);
Important: In JSX, {} can only contain expressions, not statements (like if, for, switch). Use ternary or logical operators instead.
Comments in JSX are written inside {} using JavaScript's multi‑line /* */ syntax.
Commenting in JSX
// Single-line comment outside JSX (regular JavaScript)
const element = (
<div>
{/* This is a comment inside JSX */}
<h1>Hello</h1>
{/*
Multi-line comment
spanning several lines
*/}
<p>World</p>
</div>
);
Rules for Comments
- Comments must be enclosed in
{/* ... */}. - Comments cannot be placed directly inside a tag's child position without braces.
- Single-line
//comments are not valid inside JSX (they'll be treated as text).
Best Practice: Use comments to explain complex logic or conditional rendering inside your JSX.
| Feature | HTML | JSX |
|---|---|---|
| Attribute naming | class, for, tabindex |
className, htmlFor, tabIndex |
| Inline styles | String style="color: red;" |
Object style={{ color: 'red' }} |
| Self‑closing tags | Optional for some (e.g., <img>) |
Required for elements without children (<img />) |
| JavaScript expressions | Not available | Embed with {} |
| Comments | <!-- --> |
{/* */} |
| Event handlers | onclick="..." (string) |
onClick={() => ...} (function) |
JSX is not HTML
Remember: JSX is closer to JavaScript than HTML. It gets transpiled to React.createElement calls, so it must follow JavaScript rules.
- Spread Props – Pass all props using
{...props}. - Children – Content between opening and closing tags becomes
props.children. - Keys – Required for dynamic lists (
keyprop).
function Button({ children, ...props }) {
return <button {...props}>{children}</button>;
}
// Usage: <Button className="primary" onClick={handleClick}>Click</Button>
- JSX is a syntax extension that allows writing HTML‑like markup in JavaScript.
- Use
{}to embed any JavaScript expression. - Attributes use camelCase (
className,htmlFor,onClick). - Comments are written as
{/* ... */}. - JSX is more powerful than HTML because it integrates with JavaScript logic.
- Always self‑close tags with no children.
Key Takeaway
"JSX is the heart of React's declarative nature – it lets you combine markup and logic seamlessly, making UI development intuitive and fun."
Happy coding!