JSX is the secret sauce that makes React so enjoyable to work with. It looks like HTML, feels like HTML, but it's actually JavaScript with superpowers! In this lesson, you'll learn exactly what JSX is, how it differs from regular HTML, and why React developers love it so much.
What is JSX?
JSX stands for JavaScript XML. It's a syntax extension for JavaScript that lets you write HTML-like code directly in your JavaScript files. Think of it as a way to describe what your UI should look like using a familiar HTML-like syntax, while still having the full power of JavaScript at your fingertips.
Here's a simple example:
const element = <h1>Hello, React!</h1>This looks like HTML, but it's actually JavaScript! Under the hood, this JSX gets transformed into regular JavaScript function calls that React understands.
JSX is Not HTML
This is crucial to understand: JSX is NOT HTML, even though it looks very similar. It's JavaScript code that produces HTML. When you write JSX, tools like Babel transform it into JavaScript before the browser ever sees it.
// What you write (JSX)
const element = <h1>Hello, React!</h1>
// What it becomes (JavaScript)
const element = React.createElement('h1', null, 'Hello, React!')React's createElement function creates JavaScript objects that represent DOM elements. These objects are what React uses to build and update your UI efficiently.
Why Use JSX?
You might be wondering: "Why not just use regular HTML?" Great question! Here's why JSX is so powerful:
1. JavaScript and Markup Together
JSX lets you combine your markup and logic in the same place. Instead of having separate HTML and JavaScript files that need to stay in sync, everything lives together:
function Greeting() {
const name = "Sarah"
const hour = new Date().getHours()
const timeOfDay = hour < 12 ? "morning" : hour < 18 ? "afternoon" : "evening"
return (
<div>
<h1>Good {timeOfDay}, {name}!</h1>
<p>The current time is {new Date().toLocaleTimeString()}</p>
</div>
)
}Notice how we can use variables, expressions, and logic right alongside our markup? That's the power of JSX!
2. Type Safety and IntelliSense
Because JSX is JavaScript, your code editor can provide autocompletion, type checking, and error detection. It catches mistakes before you even run your code!
3. Prevents Injection Attacks
React automatically escapes values embedded in JSX, protecting your app from XSS (Cross-Site Scripting) attacks:
// This is safe! React escapes the user input
const userInput = "<script>alert('hacked!')</script>"
function SafeComponent() {
return <div>{userInput}</div>
// Renders as text: "<script>alert('hacked!')</script>"
// NOT as executable code!
}4. Familiar Syntax
If you know HTML, you're 90% of the way to understanding JSX. The learning curve is minimal, but the power you gain is enormous.
💡 Tip: Edit the code above and click "Run" to see your changes
JSX vs HTML: Key Differences
While JSX looks like HTML, there are important differences you need to know. Let's explore them:
1. className Instead of class
In HTML, you use class to add CSS classes. In JSX, you must use className:
// ❌ Wrong - 'class' is a reserved JavaScript keyword
<div class="container">Content</div>
// ✅ Correct
<div className="container">Content</div>Why? Because class is a reserved word in JavaScript (used to create classes), React uses className instead.
2. htmlFor Instead of for
Similarly, the for attribute on labels becomes htmlFor:
// ❌ Wrong
<label for="email">Email:</label>
// ✅ Correct
<label htmlFor="email">Email:</label>
<input id="email" type="email" />3. camelCase for Attributes and Events
All attribute names in JSX use camelCase instead of lowercase or kebab-case:
// HTML style
<div onclick="handleClick()" tabindex="0" maxlength="50">
// JSX style
<div onClick={handleClick} tabIndex={0} maxLength={50}>Common examples:
onclick→onClickonchange→onChangetabindex→tabIndexmaxlength→maxLengthreadonly→readOnly
4. Self-Closing Tags Must Close
In HTML, some tags can be left open. In JSX, all tags must be properly closed:
// ❌ Wrong - These won't work in JSX
<img src="photo.jpg">
<input type="text">
<br>
// ✅ Correct - All tags must close
<img src="photo.jpg" />
<input type="text" />
<br />5. Inline Styles are Objects
In HTML, inline styles are strings. In JSX, they're JavaScript objects with camelCase property names:
// HTML style
<div style="background-color: blue; font-size: 20px;">
// JSX style
<div style={{ backgroundColor: 'blue', fontSize: '20px' }}>Notice the double curly braces:
- Outer braces: Tell JSX "this is JavaScript"
- Inner braces: Create a JavaScript object
6. Comments are Different
HTML and JSX use different comment syntax:
// HTML comments
<!-- This is an HTML comment -->
// JSX comments (inside JSX)
{/* This is a JSX comment */}
// Regular JavaScript comments (outside JSX)
// This is a single-line comment
/* This is a multi-line comment */7. Reserved Words
Some HTML attributes conflict with JavaScript keywords, so JSX uses different names:
// Common reserved word replacements
class → className
for → htmlFor
checked → defaultChecked (for uncontrolled components)
value → defaultValue (for uncontrolled components)Quick Reference: JSX → HTML Differences
classNamenotclasshtmlFornotforonClicknotonclickstyle={{ key: 'value' }}notstyle="key: value"- All tags must close with />
- Comments use {/* */} not <!-- -->
Essential JSX Rules
To write valid JSX, you need to follow these fundamental rules:
Rule 1: Return a Single Root Element
A component can only return one root element. If you want to return multiple elements, wrap them in a parent:
// ❌ Wrong - Multiple root elements
function WrongComponent() {
return (
<h1>Title</h1>
<p>Paragraph</p>
)
}
// ✅ Correct - Wrapped in div
function CorrectComponent() {
return (
<div>
<h1>Title</h1>
<p>Paragraph</p>
</div>
)
}
// ✅ Also correct - Using Fragment
function AlsoCorrect() {
return (
<>
<h1>Title</h1>
<p>Paragraph</p>
</>
)
}💡 React Fragments
Fragments (<>...</>) let you group elements without adding extra nodes to the DOM. They're perfect when you don't want an unnecessary wrapper div!
Rule 2: Close All Tags
Every tag must be closed, either with a closing tag or self-closing:
// ✅ Correct
<div>Content</div> // Regular closing tag
<img src="pic.jpg" /> // Self-closing
<input type="text" /> // Self-closing
<Component /> // Self-closing componentRule 3: Use camelCase for Most Things
JSX uses camelCase for attribute names because it turns into JavaScript, and JavaScript uses camelCase:
// ✅ Correct camelCase
<div
className="container"
onClick={handleClick}
tabIndex={0}
aria-label="Main content" // Exception: aria- and data- stay kebab-case
data-testid="my-div" // Exception: aria- and data- stay kebab-case
/>Important Exception:
Attributes starting with aria- and data- keep their hyphenated format. They don't use camelCase!
Embedding JavaScript in JSX
The real power of JSX comes from embedding JavaScript expressions using curly braces {}:
Variables and Expressions
function Profile() {
const userName = "Alice"
const age = 25
const isOnline = true
return (
<div>
<h1>{userName}</h1>
<p>Age: {age}</p>
<p>Born in: {2024 - age}</p>
<p>Status: {isOnline ? "Online" : "Offline"}</p>
<p>Random number: {Math.random()}</p>
</div>
)
}You can put any valid JavaScript expression inside curly braces:
- Variables
- Math operations
- Function calls
- Ternary operators
- Template literals
- Array methods
What You CAN'T Put in Curly Braces
You can only use expressions, not statements:
function BadExample() {
return (
<div>
{/* ❌ These won't work - they're statements, not expressions */}
{if (true) { "hello" }} // if statements
{for (let i = 0; i < 5; i++) {}} // for loops
{const x = 5} // variable declarations
{/* ✅ Use these instead */}
{true ? "hello" : "goodbye"} // ternary operator
{[1,2,3,4,5].map(i => i)} // array methods
{(() => { const x = 5; return x })()} // IIFE if you really need it
</div>
)
}JSX in Variables
You can store JSX in variables and use them later:
function FlexibleComponent() {
const header = <h1>Welcome!</h1>
const greeting = <p>Hello, user!</p>
const isLoggedIn = true
const content = isLoggedIn ? (
<div>
{header}
{greeting}
<button>Logout</button>
</div>
) : (
<div>
<h1>Please log in</h1>
<button>Login</button>
</div>
)
return content
}💡 Tip: Edit the code above and click "Run" to see your changes
JSX Attributes
You can pass attributes to JSX elements using either strings or JavaScript expressions:
String Attributes
// Use quotes for string literals
<img src="profile.jpg" alt="Profile picture" />
<a href="https://example.com">Visit</a>
<input type="email" placeholder="Enter email" />Expression Attributes
function ImageGallery() {
const imageUrl = "https://example.com/photo.jpg"
const imageAlt = "Beautiful sunset"
const imageWidth = 400
const isRounded = true
return (
<img
src={imageUrl}
alt={imageAlt}
width={imageWidth}
className={isRounded ? "rounded-full" : "rounded-none"}
/>
)
}⚠️ Don't Mix Quotes and Braces
Use either quotes (for strings) OR curly braces (for expressions), but never both for the same attribute:src="{imageUrl}" ❌ Wrongsrc={imageUrl} ✅ Correct
Boolean Attributes
Boolean attributes work a bit differently in JSX:
// These are equivalent
<input disabled={true} />
<input disabled />
// To set to false
<input disabled={false} />
// Common boolean attributes
<button disabled>Can't click</button>
<input readOnly />
<input checked />
<input required />Common JSX Gotchas
Here are some mistakes that trip up beginners (and sometimes experienced developers too!):
1. Returning Multiple Elements
// ❌ Syntax error!
return (
<h1>Title</h1>
<p>Text</p>
)
// ✅ Fix with wrapper
return (
<div>
<h1>Title</h1>
<p>Text</p>
</div>
)
// ✅ Or use Fragment
return (
<>
<h1>Title</h1>
<p>Text</p>
</>
)2. Forgetting Curly Braces
const name = "Alice"
// ❌ This displays the literal text "name"
<h1>Hello, name!</h1>
// ✅ Use curly braces for variables
<h1>Hello, {name}!</h1>3. Using String Instead of Object for Styles
// ❌ Wrong - strings don't work
<div style="color: red; font-size: 20px">Text</div>
// ✅ Correct - use object
<div style={{ color: 'red', fontSize: '20px' }}>Text</div>4. Missing Key Prop in Lists
const items = ['apple', 'banana', 'cherry']
// ❌ Missing keys - React will warn
{items.map(item => <li>{item}</li>)}
// ✅ Include unique keys
{items.map((item, index) => <li key={index}>{item}</li>)}5. Unclosed Tags
// ❌ Won't work
<img src="photo.jpg">
<br>
<input type="text">
// ✅ Close all tags
<img src="photo.jpg" />
<br />
<input type="text" />JSX Best Practices
Follow these practices to write clean, maintainable JSX:
1. Use Meaningful Variable Names
// ❌ Unclear
const x = <button>Click</button>
// ✅ Clear and descriptive
const submitButton = <button>Submit Form</button>2. Keep JSX Simple and Readable
// ❌ Too complex in JSX
return (
<div>
{users.filter(u => u.age > 18).map(u => u.name.toUpperCase()).join(', ')}
</div>
)
// ✅ Extract logic
const adultNames = users
.filter(user => user.age > 18)
.map(user => user.name.toUpperCase())
.join(', ')
return <div>{adultNames}</div>3. Use Fragments to Avoid Extra Divs
// ❌ Unnecessary wrapper div
return (
<div>
<h1>Title</h1>
<p>Content</p>
</div>
)
// ✅ Use Fragment
return (
<>
<h1>Title</h1>
<p>Content</p>
</>
)4. Format for Readability
// ❌ Hard to read
return <div className="container"><h1 className="title">Hello</h1><p className="text">World</p></div>
// ✅ Properly formatted
return (
<div className="container">
<h1 className="title">Hello</h1>
<p className="text">World</p>
</div>
)5. Be Consistent with Quotes
// Pick one style and stick with it
// ✅ Single quotes
<button className='btn' onClick={handleClick}>Click</button>
// ✅ Double quotes
<button className="btn" onClick={handleClick}>Click</button>Key Takeaways
- JSX is JavaScript XML - a syntax extension that looks like HTML
- JSX gets transformed into JavaScript before the browser runs it
- Use
classNameinstead ofclass - Use
htmlForinstead offor - All attribute names use camelCase (except aria- and data-)
- All tags must be closed with />
- Embed JavaScript expressions using curly braces
{} - Components must return a single root element (or Fragment)
- Inline styles are objects with camelCase properties
- JSX comments use
{/* */}syntax - Fragments (
<>...</>) let you group elements without extra DOM nodes
What's Next?
Now that you understand JSX syntax and how it differs from HTML, you're ready to explore one of its most powerful features: embedding JavaScript expressions and variables.
In the next lesson, we'll dive deep into using curly braces to create dynamic, interactive content. You'll learn how to display data, perform calculations, call functions, and create truly dynamic user interfaces. Get ready to unleash the full power of JavaScript in your JSX! 🚀