Getting Started with React · Lesson 3 of 31
JSX in React
JSX is a syntax extension that lets you write HTML-like markup inside JavaScript. It isn't HTML and it isn't a string: the build tool turns each tag into a function call that creates a plain JavaScript object. Once you know its handful of rules, JSX makes components easy to read.
In this lesson
- Embedding JavaScript with
{ } - Attributes:
className,htmlFor, camelCase events, inline styles - One root element and fragments
- What JSX compiles to, and why it's safe from XSS
Expressions in curly braces
Anything inside { } is a JavaScript expression: a variable, a calculation, a function call, a ternary.
const user = { firstName: "Asha", lastName: "Verma", points: 1240 };
const formatName = (u) => `${u.firstName} ${u.lastName}`;
export default function App() {
const level = user.points >= 1000 ? "Gold" : "Silver";
return (
<div>
<h1>Welcome back, {formatName(user)}</h1>
<p>Points: {user.points.toLocaleString("en-IN")}</p>
<p>Level: {level}</p>
<p>Next reward in {2000 - user.points} points</p>
<p>Today is a {["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][new Date(2026, 10, 9).getDay()]}</p>
</div>
);
}
Welcome back, Asha Verma Points: 1,240 Level: Gold Next reward in 760 points Today is a Mon
Expressions only, not statements
You can't put if, for or const inside { }. Compute values before the return, or use a ternary, && or map – all expressions. The next chapter covers conditional rendering and lists.
Attributes
const course = { title: "React.js", cover: "/img/react.png", url: "/learning/react" };
export default function App() {
const isNew = true;
return (
<article className={isNew ? "card card--new" : "card"}>
<img src={course.cover} alt={`${course.title} course cover`} width={320} />
<a href={course.url}>{course.title}</a>
<label htmlFor="email">Get updates</label>
<input id="email" type="email" placeholder="you@example.com" disabled={false} />
<p style={{ color: "#087ea4", fontWeight: 600, marginTop: 8 }}>Free course</p>
</article>
);
}
(image: React.js course cover) React.js Get updates [you@example.com…] Free course
| HTML | JSX | Why |
|---|---|---|
class | className | class is a JavaScript keyword |
for | htmlFor | for is a keyword too |
onclick | onClick | attributes are camelCase |
style="color: red" | style={{ color: "red" }} | style takes an object; numbers mean px |
<br>, <img> | <br />, <img /> | every tag must be closed |
The double braces in style={{ … }} aren't special syntax: the outer pair means "JavaScript here", the inner pair is an object literal. aria-* and data-* attributes keep their dashes.
One root element, or a fragment
A component returns one value, so JSX must have a single parent. Returning two siblings is a compile error:
export default function Profile() {
return (
<h2>Asha Verma</h2>
<p>Frontend developer</p>
);
}
main.tsx(3,5): error TS2657: JSX expressions must have one parent element.
Wrap them in a fragment, <>…</>, which groups elements without adding an extra div to the page:
function Profile() {
return (
<>
<h2>Asha Verma</h2>
<p>Frontend developer</p>
</>
);
}
export default function App() {
return (
<section>
{/* a comment inside JSX uses braces */}
<Profile />
</section>
);
}
Asha Verma Frontend developer
What JSX compiles to
// You write:
const el = <a href="/learning/react" className="link">React</a>;
// The build tool produces (React 17+ "automatic runtime"):
import { jsx as _jsx } from "react/jsx-runtime";
const el = _jsx("a", { href: "/learning/react", className: "link", children: "React" });
// …which returns a plain object, roughly:
// { type: "a", props: { href: "/learning/react", className: "link", children: "React" } }
That object is a React element – a description of what to show, not a DOM node. Lowercase tags (a, div) become HTML elements; capitalised ones (Profile) are your components. That's why component names must start with a capital letter.
JSX escapes text automatically
export default function App() {
const comment = '<img src=x onerror="alert(1)"> Nice course!'; // e.g. user input
return <p>{comment}</p>;
}
<img src=x onerror="alert(1)"> Nice course!
Safe by default
React inserts strings as text, never as HTML, so the injected tag above is shown harmlessly instead of running. The escape hatch is dangerouslySetInnerHTML={{ __html: html }} – only use it with HTML you have sanitised (for example with DOMPurify).
Practice
Try it yourself
Build a
PriceTagthat shows a product name, the price formatted as rupees, and "In stock" in green or "Sold out" in grey.Show solution
const product = { name: "Mechanical Keyboard", price: 3499, stock: 0 }; export default function App() { const inStock = product.stock > 0; return ( <div className="price-tag"> <h3>{product.name}</h3> <p>{product.price.toLocaleString("en-IN", { style: "currency", currency: "INR" })}</p> <p style={{ color: inStock ? "green" : "grey" }}>{inStock ? "In stock" : "Sold out"}</p> </div> ); }Mechanical Keyboard ₹3,499.00 Sold out
Quick check
How do you set a CSS class in JSX?
With className.
Why must component names be capitalised?
Lowercase tags are treated as HTML elements; capitalised ones as components.
How do you return two sibling elements without a wrapper div?
Wrap them in a fragment: <>…</>.
Summary
- JSX is JavaScript: { } holds expressions, attributes are camelCase, style takes an object.
- Return one root element or a fragment; close every tag.
- JSX compiles to jsx() calls that create React elements, and text is escaped automatically.
Finished this lesson?
Mark it complete to track your progress, then carry on with the next lesson.