JSX Syntax

JSX looks like HTML sitting inside JavaScript, and that's basically what it is — with a few rules of its own that trip up almost everyone the first time.

Embedding JavaScript expressions

Curly braces {} drop back into plain JavaScript from the middle of JSX markup — any expression works, including variables, function calls, and arithmetic:

JSX Greeting.jsx
function Greeting() {
  const name = "Priya";
  const hour = 14;

  return (
    <p>Hello, {name}! It's {hour >= 12 ? "afternoon" : "morning"}.</p>
  );
}
Rendered output
Hello, Priya! It's afternoon.

Only expressions work inside {} — things that produce a value. Statements like if or for don't fit inside curly braces directly, which is why the example above uses a ternary (? :) instead of a plain if.

One root element

A component can only return a single top-level element. Wrapping multiple elements in an extra <div> works, but a fragment (<>...</>) does the same job without adding an unnecessary element to the actual page:

JSX UserInfo.jsx
function UserInfo() {
  return (
    <>
      <h2>Priya Sharma</h2>
      <p>Frontend Developer</p>
    </>
  );
}
Rendered output
An <h2> reading "Priya Sharma" followed by a
<p> reading "Frontend Developer" — with no
wrapping <div> in the actual page's HTML.

Attributes: className and camelCase

JSX attributes are written in camelCase, and a couple of names change entirely to avoid colliding with JavaScript keywords:

JSX Card.jsx
function Card() {
  return (
    <div className="card" onClick={() => console.log("clicked")}>
      <label htmlFor="name">Name</label>
    </div>
  );
}
Rendered output
A div with class="card" in the real DOM, containing
a label linked to a field named "name". Clicking the
div logs "clicked" to the console.
Note: class becomes className and for becomes htmlFor because both class and for are reserved words in JavaScript. Every other HTML attribute that's normally lowercase-with-dashes, like tabindex or onclick, becomes camelCase in JSX: tabIndex, onClick. Also remember every tag needs a closing tag or a self-closing slash — <img> must be written <img />.