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:
function Greeting() {
const name = "Priya";
const hour = 14;
return (
<p>Hello, {name}! It's {hour >= 12 ? "afternoon" : "morning"}.</p>
);
}
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:
function UserInfo() {
return (
<>
<h2>Priya Sharma</h2>
<p>Frontend Developer</p>
</>
);
}
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:
function Card() {
return (
<div className="card" onClick={() => console.log("clicked")}>
<label htmlFor="name">Name</label>
</div>
);
}
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.
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 />.