Chapter 2: JSX
What is JSX?
JSX (JavaScript XML) is a syntax extension that allows you to write HTML in JavaScript:
const element = <h1>Hello World!</h1>;
This is not HTML. It's JavaScript that will be transformed into React function calls.
// This JSX:
const element = <h1 className="title">Hello</h1>;
// Is transformed to:
const element = React.createElement('h1', { className: 'title' }, 'Hello');
You don't need to write React.createElement - the compiler (Babel/Vite) does it for you.
Differences with HTML
className instead of class
class is a reserved word in JavaScript:
// HTML
<div class="container">
// JSX
<div className="container">
htmlFor instead of for
// HTML
<label for="email">
// JSX
<label htmlFor="email">
Style as object
// HTML
<div style="color: red; font-size: 16px;">
// JSX - object with camelCase
<div style={{ color: 'red', fontSize: '16px' }}>
// Or with a variable
const styles = { color: 'red', fontSize: '16px' };
<div style={styles}>
camelCase Attributes
// HTML
<button onclick="handleClick()">
<input tabindex="1">
// JSX
<button onClick={handleClick}>
<input tabIndex={1}>
Required Tag Closing
// HTML
<img src="/img/training/module2-introduction-react/photo.jpg">
<input type="text">
<br>
// JSX - always close
<img src="/img/training/module2-introduction-react/photo.jpg" />
<input type="text" />
<br />
JavaScript Expressions in JSX
Use braces {} to insert JavaScript:
Variables
const name = "Jean";
const age = 30;
return (
<div>
<p>Name: {name}</p>
<p>Age: {age}</p>
<p>Birth year: {2024 - age}</p>
</div>
);
Functions
function formatName(user) {
return `${user.firstName} ${user.lastName}`;
}
const user = { firstName: 'Jean', lastName: 'Dupont' };
return <h1>Hello, {formatName(user)}!</h1>;
Expressions, not statements
In braces, you can use expressions (which return a value), not statements (if, for, while).
// CORRECT - expressions
{name}
{2 + 2}
{formatName(user)}
{isAdmin ? 'Admin' : 'User'}
{items.length}
// INCORRECT - statements
{if (isAdmin) { return 'Admin' }} // Error!
{for (let i = 0; i < 10; i++) {}} // Error!
Conditions
Ternary Operator
To display one thing or another:
function Greeting({ isLoggedIn }) {
return (
<div>
{isLoggedIn ? (
<p>Welcome!</p>
) : (
<p>Please log in</p>
)}
</div>
);
}
&& Operator
To display something or nothing:
function Notification({ count }) {
return (
<div>
{count > 0 && (
<span className="badge">{count}</span>
)}
</div>
);
}
Warning: {count && <span>...</span>} will display 0 if count is 0, because 0 is a "falsy" but displayable value. Prefer {count > 0 && ...}.
Variables for Complex Cases
function UserStatus({ user }) {
let statusMessage;
if (user.isAdmin) {
statusMessage = <span className="admin">Admin</span>;
} else if (user.isPremium) {
statusMessage = <span className="premium">Premium</span>;
} else {
statusMessage = <span>Standard</span>;
}
return <div>{statusMessage}</div>;
}
Loops with map()
To display a list, use map():
function UserList({ users }) {
return (
<ul>
{users.map(user => (
<li key={user.id}>
{user.name}
</li>
))}
</ul>
);
}
The key Attribute
Required for lists. Allows React to identify each element:
// CORRECT - unique ID
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
// ACCEPTABLE - if no ID, use index (less performant)
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
// INCORRECT - no key
{users.map(user => (
<li>{user.name}</li> // React warning!
))}
Comparison with PHP
// PHP
<?php foreach ($users as $user): ?>
<li><?= $user['name'] ?></li>
<?php endforeach; ?>
// React
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
Fragments
A component must return a single root element. If you don't want to add an unnecessary <div>, use a Fragment:
// INCORRECT - multiple root elements
function UserInfo({ user }) {
return (
<h1>{user.name}</h1>
<p>{user.email}</p> // Error!
);
}
// CORRECT - with Fragment
function UserInfo({ user }) {
return (
<>
<h1>{user.name}</h1>
<p>{user.email}</p>
</>
);
}
// Or long syntax
import { Fragment } from 'react';
function UserInfo({ user }) {
return (
<Fragment>
<h1>{user.name}</h1>
<p>{user.email}</p>
</Fragment>
);
}
Exercises
Exercise 1: Convert to JSX
Convert this HTML to JSX:
<div class="card">
<img src="/img/training/module2-introduction-react/photo.jpg" alt="Photo">
<label for="name">Name:</label>
<input type="text" id="name" tabindex="1">
<button onclick="save()">Save</button>
</div>
Solution:
<div className="card">
<img src="/img/training/module2-introduction-react/photo.jpg" alt="Photo" />
<label htmlFor="name">Name:</label>
<input type="text" id="name" tabIndex={1} />
<button onClick={save}>Save</button>
</div>
Exercise 2: Conditional Rendering
Create a component that displays:
- "Loading..." if
loadingis true - "No results" if
itemsis empty - The list of items otherwise
Solution:
function ItemList({ loading, items }) {
if (loading) {
return <p>Loading...</p>;
}
if (items.length === 0) {
return <p>No results</p>;
}
return (
<ul>
{items.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}
Key Points to Remember
- JSX is not HTML: it's JavaScript transformed
- className instead of class, htmlFor instead of for
- Braces
{}to insert JavaScript - Ternary
? :or && for conditions - map() for loops, with a unique key
- Fragments
<></>to return multiple elements
<- Previous Chapter | Back to Module | Next Chapter: Components ->