What is JSX?
JSX (JavaScript XML) is a syntax extension for JavaScript that lets you write HTML-like code in your JavaScript files. It was created by the React team to make creating React elements more intuitive and readable.
JSX is NOT HTML: Although JSX looks similar to HTML, it's actually JavaScript under the hood. When your code runs, JSX gets transformed into regular JavaScript function calls. Understanding this distinction is crucial for mastering React.
Here's a simple example comparing JSX with plain JavaScript:
// JSX syntax (what you write)
const element = <h1 className="greeting">Hello, world!</h1>;
// What it compiles to (pure JavaScript)
const element = React.createElement(
'h1',
{ className: 'greeting' },
'Hello, world!'
);
The JSX version is much more readable and looks like the HTML you already know. This is why React developers overwhelmingly prefer JSX over plain JavaScript.
JSX Syntax Rules
JSX has specific rules you must follow. Let's explore each one:
1. All Elements Must Be Closed
In HTML, some tags like <img> and <br> don't require closing tags. In JSX, ALL tags must be closed:
// ❌ Wrong - HTML style
<img src="photo.jpg">
<br>
<input type="text">
// ✅ Correct - JSX style
<img src="photo.jpg" />
<br />
<input type="text" />
2. Use className Instead of class
Since "class" is a reserved keyword in JavaScript, JSX uses className for CSS classes:
// ❌ Wrong
<div class="container">Content</div>
// ✅ Correct
<div className="container">Content</div>
3. Use htmlFor Instead of for
Similarly, "for" is a JavaScript keyword, so use htmlFor in labels:
// ❌ Wrong
<label for="username">Username:</label>
// ✅ Correct
<label htmlFor="username">Username:</label>
4. camelCase for Attributes
JSX uses camelCase naming for attributes that would be hyphenated in HTML:
// HTML attributes → JSX attributes
onclick → onClick
onchange → onChange
tabindex → tabIndex
maxlength → maxLength
autocomplete → autoComplete
5. Must Return a Single Parent Element
JSX expressions must have exactly one root element. You can't return multiple elements without wrapping them:
// ❌ Wrong - multiple root elements
function App() {
return (
<h1>Hello</h1>
<p>Welcome</p>
);
}
// ✅ Correct - wrapped in single parent
function App() {
return (
<div>
<h1>Hello</h1>
<p>Welcome</p>
</div>
);
}
React Fragments: If you don't want to add an extra <div> wrapper, use React Fragments: <React.Fragment> or the shorthand <>. We'll cover this later in this lesson!
Embedding JavaScript Expressions
One of JSX's most powerful features is the ability to embed JavaScript expressions using curly braces {}:
function Greeting() {
const name = 'Sarah';
const age = 25;
return (
<div>
<h1>Hello, {name}!</h1>
<p>You are {age} years old.</p>
<p>Next year you will be {age + 1}.</p>
</div>
);
}
What Can Go Inside Curly Braces?
- Variables:
{userName}
- Expressions:
{2 + 2}, {price * quantity}
- Function calls:
{formatDate(today)}
- Ternary operators:
{isLoggedIn ? 'Logout' : 'Login'}
- Array methods:
{items.map(item => item.name)}
function ProductCard() {
const product = {
name: 'Laptop',
price: 999,
inStock: true
};
const tax = 0.1;
const totalPrice = product.price + (product.price * tax);
return (
<div className="product">
<h2>{product.name}</h2>
<p>Price: ${product.price}</p>
<p>Total with tax: ${totalPrice.toFixed(2)}</p>
<p>Status: {product.inStock ? 'In Stock' : 'Out of Stock'}</p>
</div>
);
}
What You CANNOT Use in JSX Expressions:
- Statements (if/else, for loops, while loops)
- Variable declarations (let, const, var)
- Function definitions
Use expressions only! For conditional rendering, use ternary operators or logical AND (&&).
JSX Attributes and Props
You can pass attributes to JSX elements just like HTML, but using camelCase and expressions:
function UserProfile() {
const imageUrl = 'https://example.com/avatar.jpg';
const altText = 'User Avatar';
const isActive = true;
return (
<div>
{/* String attributes use quotes */}
<h1 title="User Profile">Profile</h1>
{/* Expression attributes use curly braces */}
<img src={imageUrl} alt={altText} />
{/* Boolean attributes */}
<button disabled={!isActive}>Submit</button>
{/* Inline styles as objects */}
<p style={{ color: 'blue', fontSize: '18px' }}>
Welcome back!
</p>
</div>
);
}
Style Attribute Syntax: Notice the double curly braces in the style attribute: style={{ color: 'blue' }}. The outer braces indicate a JavaScript expression, and the inner braces create a JavaScript object. CSS properties use camelCase: fontSize, backgroundColor, etc.
Conditional Rendering
JSX allows you to conditionally render content using several techniques:
1. Ternary Operator (condition ? true : false)
function LoginButton({ isLoggedIn }) {
return (
<div>
{isLoggedIn ? (
<button>Logout</button>
) : (
<button>Login</button>
)}
</div>
);
}
2. Logical AND Operator (&&)
Use && when you want to render something only if a condition is true:
function Notification({ hasNewMessages, messageCount }) {
return (
<div>
<h1>Dashboard</h1>
{hasNewMessages && (
<div className="alert">
You have {messageCount} new messages!
</div>
)}
</div>
);
}
How && Works in JSX: JavaScript evaluates condition && expression. If the condition is true, it returns the expression. If false, it returns false (which React doesn't render). This is a concise way to conditionally show elements.
3. Element Variables
For complex conditions, store JSX in variables:
function Greeting({ user }) {
let content;
if (user.isAdmin) {
content = <h1>Welcome back, Admin {user.name}!</h1>;
} else if (user.isVIP) {
content = <h1>Welcome, VIP {user.name}!</h1>;
} else {
content = <h1>Hello, {user.name}!</h1>;
}
return (
<div>
{content}
<p>Last login: {user.lastLogin}</p>
</div>
);
}
Rendering Lists
To render lists in React, use JavaScript's .map() method to transform arrays into JSX elements:
function ShoppingList() {
const items = ['Apples', 'Bananas', 'Oranges', 'Milk', 'Bread'];
return (
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
}
For objects with unique IDs, use the ID as the key:
function UserList() {
const users = [
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' },
{ id: 3, name: 'Charlie', email: 'charlie@example.com' }
];
return (
<div>
{users.map(user => (
<div key={user.id} className="user-card">
<h3>{user.name}</h3>
<p>{user.email}</p>
</div>
))}
</div>
);
}
The "key" Prop is Required: When rendering lists, React requires a unique key prop for each element. This helps React identify which items have changed, been added, or removed. Always use stable, unique IDs when available. Avoid using array indices as keys for dynamic lists (it's OK for static lists that never change).
React Fragments
React Fragments let you group multiple elements without adding extra nodes to the DOM:
// Using React.Fragment (long syntax)
function Table() {
return (
<table>
<tbody>
<React.Fragment>
<tr><td>Row 1</td></tr>
<tr><td>Row 2</td></tr>
</React.Fragment>
</tbody>
</table>
);
}
// Using Fragment shorthand (recommended)
function Table() {
return (
<table>
<tbody>
<>
<tr><td>Row 1</td></tr>
<tr><td>Row 2</td></tr>
</>
</tbody>
</table>
);
}
When to Use Fragments: Use fragments when you need to return multiple adjacent elements without wrapping them in a <div>. This is especially useful for maintaining correct HTML structure (like in tables) and avoiding unnecessary DOM nesting.
Fragments can also accept the key attribute when rendering lists (but only with the long syntax):
function Glossary({ items }) {
return (
<dl>
{items.map(item => (
<React.Fragment key={item.id}>
<dt>{item.term}</dt>
<dd>{item.definition}</dd>
</React.Fragment>
))}
</dl>
);
}
Comments in JSX
Adding comments in JSX requires special syntax:
function Example() {
return (
<div>
{/* This is a single-line comment in JSX */}
{/*
This is a
multi-line comment
in JSX
*/}
<h1>Hello World</h1>
{/* Comments inside attributes work too */}
<input
type="text"
{/* disabled */}
placeholder="Enter text"
/>
</div>
);
}
// Regular JavaScript comments work outside JSX
// This is a regular comment
JSX vs HTML: Key Differences Summary
HTML vs JSX Differences:
1. Class attribute:
HTML: class="my-class"
JSX: className="my-class"
2. For attribute:
HTML: <label for="input">
JSX: <label htmlFor="input">
3. Self-closing tags:
HTML: <img src="photo.jpg">
JSX: <img src="photo.jpg" />
4. Style attribute:
HTML: style="color: red; font-size: 18px"
JSX: style={{ color: 'red', fontSize: '18px' }}
5. Event handlers:
HTML: onclick="handleClick()"
JSX: onClick={handleClick}
6. Boolean attributes:
HTML: <input disabled>
JSX: <input disabled={true} /> or <input disabled />
7. Multiple root elements:
HTML: Can have multiple
JSX: Must have single parent or Fragment
Exercise 1: Basic JSX Practice
Create a component called PersonCard that displays a person's information. Use JSX to render:
- A heading with the person's full name
- A paragraph with their age (calculate years until 100)
- An image with their avatar (use a placeholder URL)
- A paragraph showing "Active" if they're active, otherwise "Inactive"
- Apply CSS classes and inline styles
Data to use:
const person = {
firstName: 'John',
lastName: 'Doe',
age: 28,
avatar: 'https://via.placeholder.com/150',
isActive: true
};
Exercise 2: Conditional Rendering
Create a WeatherCard component that displays weather information with conditional rendering:
- Show a sun icon ☀️ if temperature > 25°C
- Show a cloud icon ☁️ if temperature is between 15-25°C
- Show a snowflake ❄️ if temperature < 15°C
- Display a warning message if temperature > 35°C or < 0°C
- Show "Bring an umbrella" if isRaining is true
Data to use:
const weather = {
temperature: 28,
isRaining: false,
location: 'New York'
};
Exercise 3: Rendering Lists
Create a BookshelfComponent that displays a list of books:
- Map through the books array to create a card for each book
- Each card should show: title, author, year, and rating
- Add a ⭐ star for each point of rating (e.g., 5 stars for rating 5)
- Apply different background colors based on rating (green > 4, yellow 3-4, red < 3)
- Use proper keys for list items
Data to use:
const books = [
{ id: 1, title: '1984', author: 'George Orwell', year: 1949, rating: 5 },
{ id: 2, title: 'To Kill a Mockingbird', author: 'Harper Lee', year: 1960, rating: 5 },
{ id: 3, title: 'The Great Gatsby', author: 'F. Scott Fitzgerald', year: 1925, rating: 4 },
{ id: 4, title: 'Moby Dick', author: 'Herman Melville', year: 1851, rating: 3 }
];
Summary
In this lesson, you mastered JSX fundamentals:
- JSX is a syntax extension that looks like HTML but is actually JavaScript
- All JSX tags must be closed (self-closing for single tags)
- Use
className instead of class, htmlFor instead of for
- Embed JavaScript expressions in JSX using curly braces
{}
- JSX attributes use camelCase (onClick, onChange, etc.)
- Conditional rendering uses ternary operators, && operator, or element variables
- Render lists using
.map() with unique key props
- React Fragments (
<></>) group elements without extra DOM nodes
- Comments in JSX use
{/* comment */} syntax
In the next lesson, we'll explore React components in depth, learning how to create reusable, composable pieces of UI with function components!