React FundamentalsPart 2

JSX — It Looks Like HTML, but It's Actually JavaScript

A close look at JSX, the syntax React uses to describe the screen. Why it resembles HTML yet differs, what the curly braces do, and why you write className instead of class — framed against your web experience.

Last time we said a component is “a function that returns a blueprint for drawing the screen.” But you were probably wondering about that blueprint itself — the HTML-looking thing that comes after return. Tags sitting inside a function definitely look strange the first time. The name of that syntax is JSX.

For anyone with web experience, JSX is a double-edged sword. It resembles HTML, which lowers the barrier to entry — but by exactly that much, it trips you up when you wave it off as “probably just HTML.” So today let’s cleanly separate what JSX shares with HTML and what it doesn’t.


JSX isn’t HTML — it’s JavaScript

JSX is short for JavaScript XML. The XML in the name makes it look like markup, but the heart of it is the JavaScript in front. JSX isn’t a separate markup language; it’s a syntax extension that lets you write markup inside JavaScript.

const element = <h1>Hello</h1>;

The browser doesn’t understand this line as-is. During the build it’s converted into a plain JavaScript function call, like this:

const element = React.createElement('h1', null, 'Hello');

So writing a tag is really calling a function, and JSX is just the nice-looking shell that lets you write it readably. The accurate mental model isn’t “HTML bolted onto JS” but “JS borrowing a syntax that looks like markup.” Hold onto this and every difference below explains itself.

By the way, since React 17 the conversion changed, so you no longer need to write import React at the top of a file just to use JSX. That’s why you’ll see that import in older code.


Curly braces {} — the door back into JavaScript

Because JSX is JavaScript, you can step back out into JavaScript in the middle of markup. That doorway is the curly braces {}.

const name = "Karina";
const element = <h1>Hello, {name}</h1>;

Inside {} you can put not just variables but any expression that produces a value — arithmetic, function calls, and so on.

<p>{1 + 2}</p>              {/* 3 */}
<p>{user.isAdmin ? 'Admin' : 'Member'}</p>

But only “expressions that become a value” are allowed. Statements like if or for can’t go in there. This distinction is annoying at first, but once you think of “a {} inside JSX as a slot that expects a single value,” it clicks quickly.


The little things that differ from HTML

For all the resemblance, there are points where they diverge — and every reason boils down to “JSX is JavaScript.”

HTMLJSXWhy
class="box"className="box"class is a reserved word in JavaScript
for="id"htmlFor="id"for is reserved too (the loop)
onclick="..."onClick={...}attributes are camelCase, value is a function
style="color:red"style={{ color: 'red' }}an object, not a string
<br><br />every tag must be closed

Look closely at style. The outer {} is “the door into JavaScript,” the inner {} is “an object,” so there are two layers of braces. A hyphenated property like background-color can’t be a JavaScript object key, so you write it camelCase as backgroundColor. It resembles web styling, but it’s ultimately a JavaScript object.


The return must be a single piece

A component returns a screen blueprint — and its top level must be a single element. Just as a function returns one value, JSX too must gather into one result.

// ❌ can't return two sibling elements side by side
return (
  <h1>Title</h1>
  <p>Body</p>
);

But it’d be a shame to wrap things in a meaningless <div> just to satisfy that and clutter the markup. That’s what the Fragment, the empty tag <>...</>, is for.

return (
  <>
    <h1>Title</h1>
    <p>Body</p>
  </>
);

<> groups several siblings into one without leaving any actual element on the screen.


Why build it this way at all?

Mixing markup and logic in one file, one function, feels odd at first. For a long time we were taught to keep HTML with HTML and JavaScript with JavaScript, as a virtue.

But recall the idea of the component from last time and the story changes. When you build a single button, its appearance (markup) and its behavior (logic) are really one inseparable lump. JSX takes the view that “the screen and the logic that makes it were one body all along” and turns it into syntax. You’re gathering code by concern (a single component) rather than by file type.

Now you’ve got a feel for how the screen gets written. Next time we’ll look at how, when composing these components, a parent hands values down to a child — Props.