Understanding JSX in React
If you looked at the code in our previous post and thought, “Wait, isn’t that HTML sitting inside JavaScript?” — you’re right to notice that, and it’s the very first thing that surprises most newcomers to React. That syntax is called JSX, and understanding it properly will make everything else in React click into place much faster.
In this post, we’ll break down what JSX actually is, how it works behind the scenes, and the rules you need to follow when writing it.
What Is JSX?
JSX stands for JavaScript XML. It’s a syntax extension for JavaScript that lets you write markup (similar to HTML) directly inside your JavaScript files.
Here’s a simple example:
const greeting = <h1>Hello, world!</h1>At first glance, this looks like you’re mixing HTML and JavaScript, which shouldn’t normally work — and technically, browsers don’t understand this syntax at all. JSX is not valid JavaScript on its own. It needs to be converted into regular JavaScript before it can run, and that’s where a transpiler like Babel comes in.
What Happens Behind the Scenes
When you write:
const element = <h1 className="title">Hello, world!</h1>Babel transpiles this into a regular JavaScript function call that looks like this:
const element = React.createElement(
'h1',
{ className: 'title' },
'Hello, world!'
)React.createElement() returns a plain JavaScript object describing what should appear on the screen — something like:
{
type: 'h1',
props: {
className: 'title',
children: 'Hello, world!'
}
}This object is what React calls a React element. React then uses this object to figure out what needs to be rendered (or updated) in the actual browser DOM. This is also the foundation of how the Virtual DOM works — but we’ll dig deeper into that in a later post.
The key takeaway: JSX is just syntactic sugar for React.createElement() calls. It exists purely to make your code more readable and closer to how the final UI actually looks.
Rules of Writing JSX
JSX looks like HTML, but it isn’t HTML, and it comes with its own set of rules.
1. You Must Return a Single Root Element
A component can only return one parent element. This is invalid:
function App() {
return (
<h1>Title</h1>
<p>Paragraph</p>
)
}You need to wrap these in a single parent:
function App() {
return (
<div>
<h1>Title</h1>
<p>Paragraph</p>
</div>
)
}If you don’t want to add an extra <div> to your actual DOM output, you can use a Fragment instead:
function App() {
return (
<>
<h1>Title</h1>
<p>Paragraph</p>
</>
)
}The <>...</> syntax is shorthand for React.Fragment, and it groups elements together without adding any extra node to the rendered HTML.
2. Use className Instead of class
Since class is a reserved keyword in JavaScript, JSX uses className for adding CSS classes:
<div className="container">Content</div>3. All Tags Must Be Closed
Even self-closing HTML elements like <img> or <br> need an explicit closing slash in JSX:
<img src="logo.png" alt="Logo" />
<br />4. Use camelCase for Attributes
Most HTML attributes are written in camelCase in JSX instead of lowercase or hyphenated form:
<button onClick={handleClick} tabIndex={0}>Click Me</button>Common examples: onclick → onClick, tabindex → tabIndex, readonly → readOnly.
Embedding JavaScript Expressions in JSX
One of JSX’s most powerful features is the ability to embed JavaScript expressions directly inside your markup using curly braces {}.
function Greeting() {
const name = "Sarah"
const isLoggedIn = true
return (
<div>
<h1>Hello, {name}!</h1>
<p>{isLoggedIn ? "Welcome back!" : "Please log in."}</p>
<p>2 + 2 equals {2 + 2}</p>
</div>
)
}You can put any valid JavaScript expression inside {} — variables, ternary conditions, function calls, arithmetic, and so on. What you can’t put inside {} are statements like if, for, or while, since those aren’t expressions. (We’ll cover how to handle conditional rendering properly in an upcoming post.)
JSX and Comments
Since JSX blurs the line between HTML and JavaScript, writing comments inside JSX requires curly braces too:
function App() {
return (
<div>
{/* This is a comment inside JSX */}
<h1>Hello!</h1>
</div>
)
}Why Does React Use JSX at All?
You might wonder — couldn’t React just use React.createElement() directly and skip JSX altogether? Technically, yes. But in practice, JSX offers real advantages:
- Readability — Markup that visually resembles the rendered output is much easier to reason about than deeply nested function calls.
- Tooling support — Editors like VS Code offer autocompletion, syntax highlighting, and error checking for JSX.
- Colocation — JSX allows UI structure and logic to live together in the same file, which fits naturally with React’s component-based philosophy.
Here’s a side-by-side comparison to see the difference for yourself:
Without JSX:
React.createElement('div', { className: 'card' },
React.createElement('h2', null, 'Product Name'),
React.createElement('p', null, 'Product description goes here.')
)With JSX:
<div className="card">
<h2>Product Name</h2>
<p>Product description goes here.</p>
</div>The JSX version is dramatically easier to scan and understand — especially as your components grow larger.
Common Mistakes Beginners Make with JSX
- Forgetting to wrap multiple elements in a parent tag or Fragment.
- Using
classinstead ofclassName, which silently fails without an error in the browser console. - Trying to use statements (
if,for) inside{}instead of expressions. - Forgetting to close self-closing tags like
<input>or<img>. - Directly rendering objects — JSX can render strings, numbers, arrays, and React elements, but trying to render a plain object directly (e.g.,
{someObject}) will throw an error.
Recap
In this post, you learned:
- JSX is a syntax extension that lets you write UI markup inside JavaScript
- Under the hood, JSX is transpiled by Babel into
React.createElement()calls - The rules JSX follows: single root element,
classNameinstead ofclass, closing all tags, and camelCase attributes - How to embed JavaScript expressions inside JSX using
{} - Why JSX makes React code more readable and maintainable
Now that you understand how React describes UI using JSX, the next logical step is learning how to break your UI into reusable, independent pieces. In the next post, we’ll dive into Components — the fundamental building blocks of every React application.