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 loading is true
  • "No results" if items is 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

  1. JSX is not HTML: it's JavaScript transformed
  2. className instead of class, htmlFor instead of for
  3. Braces {} to insert JavaScript
  4. Ternary ? : or && for conditions
  5. map() for loops, with a unique key
  6. Fragments <></> to return multiple elements

<- Previous Chapter | Back to Module | Next Chapter: Components ->