Blog
3 min read

What Is JSX? The HTML-Like Syntax in React, Explained

JSX lets you write HTML-looking markup inside JavaScript, and it's how React components describe their UI. What it compiles to, the rules that differ from HTML (className, closing tags, one parent), embedding JavaScript with curly braces, lists, conditionals, and JSX vs TSX.

If you open a React file, you'll see something that looks like HTML sitting in the middle of JavaScript:

function Welcome() {
  const name = 'Ada'
  return <h1 className="title">Hello, {name}</h1>
}

That HTML-looking part is JSX. It's not HTML, and browsers can't run it directly — it's a syntax that gets converted into regular JavaScript before your app runs. (What is React?)

What it turns into

A build tool (Vite, Next.js, etc.) converts this:

<h1 className="title">Hello, {name}</h1>

into roughly this:

jsx('h1', { className: 'title', children: ['Hello, ', name] })

JSX is just a much more readable way of writing those function calls. (What is Vite?)

Rules that differ from HTML

className, not class

class is a reserved word in JavaScript, so JSX uses className. Similarly htmlFor instead of for on labels.

Every tag must close

<img> and <br> are fine in HTML, but JSX needs <img /> and <br />.

Attributes are camelCase

onclick → onClick, tabindex → tabIndex. Exceptions: aria-* and data-* stay as they are.

style takes an object

<div style={{ backgroundColor: 'navy', marginTop: 16 }} />

Outer braces = "JavaScript here", inner braces = the object.

One parent element

A component must return a single element. Wrap siblings in a <div> or an empty fragment:

return (
  <>
    <h1>Title</h1>
    <p>Text</p>
  </>
)

Curly braces = JavaScript

Anything inside { } is a JavaScript expression:

<p>Total: {price * quantity}</p>
<p>{user.isAdmin ? 'Admin' : 'Member'}</p>
<img src={avatarUrl} alt={user.name} />

Expressions only — not statements like if or for. That's why the next two patterns exist.

Conditionals

{isLoggedIn ? <Dashboard /> : <Login />}
{error && <p className="error">{error}</p>}

Careful with && and numbers: {count && <Badge />} shows a literal 0 when count is zero. Use {count > 0 && <Badge />}.

Lists

Use .map() to turn an array into elements, with a unique key on each:

<ul>
  {todos.map(todo => (
    <li key={todo.id}>{todo.title}</li>
  ))}
</ul>

Forgetting the key gives the familiar warning. (Unique "key" prop warning, JavaScript array methods)

Components are capitalised

<button> is an HTML element; <Button> is your component. React decides which is which by the capital letter.

JSX vs TSX

.jsx files are JavaScript with JSX. .tsx files are TypeScript with JSX — the same syntax plus types. Most AI app builders now produce .tsx. (JavaScript vs TypeScript)

Is JSX safe?

Text inside { } is automatically escaped, so user input can't inject HTML or scripts. The exception is dangerouslySetInnerHTML — the name is a warning. (XSS explained)

Common errors

  • "Adjacent JSX elements must be wrapped in an enclosing tag" — return one parent or a fragment.
  • "Objects are not valid as a React child" — you put an object inside { }. (Fix it)
  • Unexpected token < in a .js file — the build tool isn't set up to handle JSX in that file.

EasySpawn runs your React app on a server with Claude Code built in — ask it to explain any JSX you don't understand, right next to the running app. See how it works or join the waitlist.

Related: React Props Explained · What Is React? · HTML, CSS, and JavaScript Explained · React useState Explained

Keep reading