ReactJSX & Componentsbeginner
Updated:

JSX Syntax Guide

6 min read

Master JSX: how to embed expressions, set attributes, render lists and conditionals, and avoid the common syntax errors that break React components.

TL;DR – Quick Answer

JSX is a syntax extension for JavaScript that lets you write HTML-like markup directly inside your React code. A build tool converts each JSX element into a React.createElement call before it runs in the browser. You embed dynamic values with curly braces, use camelCase attribute names like className, and always return a single root element from a component.

On This Page

JSX is the syntax that makes React code look the way it does — HTML-like tags sitting comfortably inside JavaScript files. It is the first thing that feels magical about React and, for many beginners, the first thing that produces confusing errors. This guide gives you the rules and the reasoning so JSX stops being mysterious.

JSX stands for JavaScript XML. It is not a template language and it is not a string; it is a thin syntax layer that a build tool (like the one bundled with Vite) compiles into ordinary JavaScript function calls before your code ever reaches the browser.

What JSX compiles into

When you write JSX, a compiler transforms it. This line:

const heading = <h1 className="title">Hello CodeBegun</h1>;

becomes roughly this plain JavaScript:

const heading = React.createElement(
  "h1",
  { className: "title" },
  "Hello CodeBegun"
);

You almost never write createElement by hand, but knowing that JSX is just JavaScript underneath explains every rule that follows. Attributes become object properties. Child elements become arguments. And because it compiles to a JavaScript expression, JSX can only ever produce one value — which is why a component must return a single root element. If you are still fuzzy on how components fit together, review what React is first.

Embedding JavaScript with curly braces

The single most-used JSX feature is { }. Inside curly braces you can put any JavaScript expression — a variable, a math operation, a function call, a ternary:

function Profile() {
  const name = "Praneeth";
  const scores = [8, 9, 10];
  const average = scores.reduce((a, b) => a + b, 0) / scores.length;

  return (
    <div>
      <p>Student: {name}</p>
      <p>Average score: {average.toFixed(1)}</p>
      <p>Status: {average >= 8 ? "On track" : "Needs practice"}</p>
    </div>
  );
}

export default Profile;

The key word is expression. An expression produces a value. A statement (like a full if block or a for loop) does not, so it cannot go inside curly braces. This one distinction explains most "why won't my JSX work" questions.

Common mistake: Writing {if (x) { ... }} inside JSX. It fails because if is a statement, not an expression. Use a ternary {x ? a : b} for inline choices, or compute the value above the return and just drop the variable in.

Attributes use camelCase

HTML attributes carry over to JSX with two important adjustments. First, most multi-word attributes become camelCase: onclick becomes onClick, tabindex becomes tabIndex. Second, two attributes are renamed outright because their HTML names are reserved JavaScript words:

HTML JSX
class className
for htmlFor
onclick onClick
tabindex tabIndex

You pass values with quotes for strings and curly braces for JavaScript:

<img src={logoUrl} alt="CodeBegun logo" className="brand-logo" />

Note that self-closing tags must close with />. In HTML you can get away with a bare <img> or <br>; in JSX the slash is mandatory or you get a compile error.

Returning one parent element

Because JSX compiles to a single expression, a component can return only one root node. This is invalid:

// ❌ Two siblings with no wrapper — syntax error
return (
  <h2>Title</h2>
  <p>Body</p>
);

You have two fixes. Wrap the elements in a container like a <div>, or — when you do not want an extra DOM node — use a Fragment, written as empty tags:

function Card() {
  return (
    <>
      <h2>React Track</h2>
      <p>Components, hooks, and routing.</p>
    </>
  );
}

export default Card;

The <>...</> Fragment groups the siblings without adding a wrapper div to the actual page. This keeps your HTML clean, which matters for styling and accessibility.

Conditional rendering

Since you cannot use if inside JSX, you render conditionally with expressions. There are three idiomatic patterns.

The ternary for either/or:

{isLoggedIn ? <Dashboard /> : <LoginButton />}

The logical && for show-or-nothing:

{cartItems.length > 0 && <Badge count={cartItems.length} />}

And computing ahead of the return for anything complex:

function Status({ score }) {
  let label;
  if (score >= 9) label = "Excellent";
  else if (score >= 7) label = "Good";
  else label = "Keep practicing";

  return <span>{label}</span>;
}

Pro tip: With &&, be careful using a number as the left side. {count && <Badge />} will literally render 0 on screen when count is zero, because 0 is falsy but still a renderable value. Convert to a real boolean with {count > 0 && <Badge />}.

Rendering lists

You render collections by mapping an array to JSX elements. Every element in the list needs a key — a stable, unique identifier that helps React track items across re-renders:

function StudentList() {
  const students = [
    { id: 101, name: "Raju" },
    { id: 102, name: "Jaswanth" },
    { id: 103, name: "Narasimha" },
  ];

  return (
    <ul>
      {students.map((s) => (
        <li key={s.id}>{s.name}</li>
      ))}
    </ul>
  );
}

export default StudentList;

Use a real unique id from your data as the key whenever possible. Using the array index as a key is a common shortcut that causes subtle bugs when items are added, removed, or reordered, because the index of an item changes even though the item itself did not.

Interview note: "Why do lists need keys in React?" is one of the most common React interview questions. The complete answer: keys give each item a stable identity so React's diffing can match old and new elements correctly, updating only what changed. Then add the warning about not using array indices for dynamic lists. This and related questions are collected in the React interview questions guide.

Styling in JSX

Inline styles in JSX are objects, not strings, and their property names are camelCase:

const boxStyle = { backgroundColor: "#0f172a", padding: "12px" };

<div style={boxStyle}>Highlighted</div>

Notice the double braces when written inline: style={{ ... }}. The outer braces enter JavaScript; the inner braces are the object literal. Most real projects, however, use CSS classes via className or a CSS framework rather than heavy inline styles.

What renders and what does not

JSX has clear rules about which values actually appear on screen when you drop them in curly braces. Strings and numbers render as-is. But four values render nothing: false, null, undefined, and true. This is deliberate and it is what makes the && conditional pattern work — when the left side is false, React renders nothing rather than the word "false".

function Notice({ message }) {
  return (
    <div>
      {message}          {/* renders the string */}
      {null}             {/* renders nothing */}
      {false}            {/* renders nothing */}
      {[1, 2, 3]}        {/* renders 123 — arrays are flattened */}
    </div>
  );
}

Arrays are flattened and each item rendered in order, which is exactly why .map() works for lists. Objects, however, cannot be rendered directly — {someObject} throws the classic "Objects are not valid as a React child" error. When you hit that error, you are almost always trying to render an object where you meant to render one of its properties.

Spreading props

When you already have an object of properties, you can spread it onto an element instead of writing each attribute by hand. This mirrors the spread operator from plain JavaScript:

const inputProps = { type: "text", placeholder: "Name", maxLength: 40 };

<input {...inputProps} />

This is handy for passing a bundle of props through a wrapper component, but use it thoughtfully — spreading unknown props onto a DOM element can leak invalid attributes. It is a tool worth knowing and applying deliberately, not everywhere.

Comments and whitespace

Comments inside JSX go in curly braces as JavaScript comments: {/* like this */}. Regular <!-- HTML comments --> do not work. JSX also collapses whitespace much like HTML, so you control spacing with layout and CSS rather than by adding spaces in the markup.

Putting it together

JSX is small once you internalize four rules: everything dynamic goes in { } expressions, attributes are camelCase (with className and htmlFor renamed), a component returns exactly one root (use a Fragment for siblings), and lists need stable keys. Master those and you can read and write the vast majority of React code you will meet.

The next building block is making components respond to change. State and the hooks that manage it are covered in the React hooks introduction, and when you start capturing user input you will apply JSX rules directly in controlled form components. To see JSX used across a complete first app, work through the beginner React tutorial. The best way to lock this in is to open a Vite project and rewrite each example above from memory until the syntax feels automatic.

Frequently Asked Questions

Is JSX required to use React?
No, JSX is optional in theory. You could write React using React.createElement calls directly, but almost nobody does because it is verbose and hard to read. Every real project and tutorial uses JSX, so it is effectively required in practice.
Why is it className instead of class in JSX?
Because class is a reserved word in JavaScript, and JSX compiles to JavaScript. React uses className to set the CSS class instead. Similarly, for is written as htmlFor. These are the two renamed attributes beginners forget most often.
Can I write if statements inside JSX?
Not directly. Curly braces in JSX accept expressions, not statements, so a full if block will not work inside them. Instead you use the ternary operator or the && operator for inline conditionals, or you compute the value in an if block before the return.
Why does React need a key when rendering a list?
Keys give each list item a stable identity so React can track which items changed, moved, or were removed between renders. Without keys, React may re-render incorrectly or slowly. Use a unique id from your data as the key, not the array index when the list can change.
What does it mean that JSX must have one parent element?
A component must return a single root node because JSX compiles to a single function call. If you need to return sibling elements without adding an extra wrapper div, wrap them in a Fragment, written as empty angle brackets.

Want to Build Your Career in Java Full Stack with AI?

Join CodeBegun and train with working industry engineers — Explore the Program

Apply for Demo Class →
Siva Prasad Galaba
Founder, CodeBegun · Staff Engineer

Founder of CodeBegun. 15+ years building Java systems at companies like Crunchyroll. Teaches Java, Spring Boot and system design the way the industry actually works, and mentors students through projects, mock interviews and placement preparation.

Technically reviewed by CodeBegun Technical TeamLast reviewed 15 July 2026 LinkedIn
Chat with us