React BasicsBeginner8 min02 / 9

JSX

Learn how JSX lets you write HTML-like UI directly in JavaScript, embed dynamic values with {}, and understand exactly what the browser actually runs.

When you look at a React component for the first time, something feels off. There's HTML sitting right inside a JavaScript function — no quotes, no template strings, just tags. That's JSX, and it's one of the things that makes React feel so natural to work with.

JSX isn't magic, and it isn't a separate language. It's a compact shorthand that your build tool transforms into regular JavaScript before it ever reaches the browser. Once you understand what's really going on, JSX will feel like one of the best ideas in modern web development.

Think of it like

Shorthand, like texting

When you text "omw" you mean "on my way" — shorthand your reader mentally expands. JSX works the same way: you write <Button color="blue">Click me</Button> and the build tool expands it into a full React.createElement(...) call. You write the short form; the computer fills in the rest.

JSX is syntactic sugar — the top line is what you type, the bottom is what runs in the browser.
// What you write (JSX):
const element = <h1 className="title">Hello!</h1>;

// What the build tool produces (plain JS):
const element2 = React.createElement(
  "h1",
  { className: "title" },
  "Hello!"
);

#Embedding Expressions with {}

The curly braces {} are JSX's escape hatch back into JavaScript. Anything inside them is a JavaScript expression — a variable, a calculation, a ternary. This is how your UI stays connected to live data. Statements like if blocks or for loops don't work inside {}; use ternaries for conditionals and .map() for lists instead.

Variables, math, and ternaries all work inside {}.
const user = { name: "Maya", score: 42 };
const isWinner = user.score > 40;

function ScoreCard() {
  return (
    <div>
      <h2>Player: {user.name}</h2>
      <p>Score: {user.score * 2}</p>
      <p>{isWinner ? "You won!" : "Try again"}</p>
    </div>
  );
}

#HTML Differences: className, Self-Closing Tags, and camelCase Events

JSX looks like HTML but follows JavaScript's rules, so a few attributes change:

  • `className` instead of `class`class is a reserved keyword in JavaScript.
  • Every tag must be closed — void elements like <img> and <input> need a self-closing slash: <img />.
  • camelCase event namesonclick becomes onClick, onchange becomes onChange.
className, self-closing />, and camelCase events are the three main HTML-to-JSX adjustments.
// HTML:
// <button class="btn" onclick="save()">Save</button>
// <img src="photo.png">

// JSX equivalents:
function Form() {
  return (
    <div className="form">
      <img src="/photo.png" alt="Profile" />
      <button className="btn" onClick={save}>Save</button>
    </div>
  );
}
Common mistake

JSX must have exactly one root element — use Fragments to fix it

A component's return can only return one top-level element. Returning two siblings side-by-side causes a syntax error. Wrap them in a Fragment (<>...</>) to satisfy the rule without adding an extra DOM node:

```jsx // Broken: return (<h1>Title</h1><p>Body</p>);

// Fixed with a Fragment: return ( <> <h1>Title</h1> <p>Body</p> </> ); ```

Fragments are especially useful inside flex containers or table rows, where a stray <div> would break your layout.

#How JSX Compiles to Function Calls

Every JSX element compiles to React.createElement(tag, props, ...children). For HTML elements the tag is a plain string ("div"); for your own components it's the actual function reference (Button, not "Button"). This is exactly why component names must start with a capital letter — that capital is how the compiler knows to pass the function, not a string.

Nested JSX becomes nested createElement calls — that's all it ever is.
// JSX you write:
function Alert({ message }) {
  return (
    <div className="alert">
      <strong>Notice:</strong> {message}
    </div>
  );
}

// What the compiler produces:
function Alert({ message }) {
  return React.createElement(
    "div",
    { className: "alert" },
    React.createElement("strong", null, "Notice:"),
    " ",
    message
  );
}
Quick check

Which of the following is valid JSX?

Key takeaways

  • JSX compiles to React.createElement() calls — it's readable shorthand, not a separate language.
  • Use {} to embed any JavaScript expression (variables, math, ternaries) directly in your markup.
  • Write className instead of class, close every void element with />, and use camelCase event names.
  • A component can only return one root element — wrap siblings in a Fragment (<>...</>) to avoid extra DOM nodes.
  • Capital letters on component names tell the compiler to pass a function reference, not an HTML string.
Practice challenges
Test yourself · earn XP
0/4
Fix the bug#1

This code has a bug — what's wrong?

fix-bug
function Profile() {
  return (
    <div class="card">
      <img src="/me.png">
      <h2>Maya</h2>
    </div>
  );
}
Fill in the blank#2

A component can only return ONE top-level element. To return two siblings without adding an extra DOM node, wrap them in a Fragment. Fill in the opening Fragment tag.

function Header() {
  return (
    
      <h1>Title</h1>
      <p>Body</p>
    </>
  );
}
Predict the output#3

The value inside {} is a JavaScript expression. What text does the rendered <p> contain?

predict-output
const user = { name: "Maya", score: 42 };
const isWinner = user.score > 40;

function ScoreCard() {
  return <p>{isWinner ? "You won!" : "Try again"}</p>;
}
Reorder the lines#4

Arrange these lines into a valid ScoreCard component that embeds a name, a calculation, and a ternary using {}, all inside a single root <div>.

1
  );
2
  return (
3
      <p>{score > 40 ? "You won!" : "Try again"}</p>
4
function ScoreCard({ name, score }) {
5
    <div>
6
}
7
    </div>
8
      <p>Score: {score * 2}</p>
9
      <h2>Player: {name}</h2>
Your turn
Practice exercise

Build a WeatherCard component that displays: a city name in an <h2>, the temperature in a <p>, and a condition label (e.g. 'Sunny') in a <span> with className="condition". Embed all three values from the provided weather object using {}. Return everything inside a Fragment so no extra <div> is added to the DOM.

Try it live — edit the code and hit Run to see it rendered:

solution.jsx · editable