JSX Syntax
JSX Syntax explains JSX expressions, attributes, fragments, event handlers, conditional and list rendering, inline styles, accessibility, compilation, and common syntax mistakes.
JSX is one of the most important concepts in React.
It allows you to write HTML-like markup directly inside JavaScript, making React UI easier to describe and compose.
A simple example:
function Welcome() {return <h1>Hello, React!</h1>;}
The <h1>Hello, React!</h1> part is JSX.
Learning Objectives
By the end of this lesson, you will understand:
- What JSX is
- Why React uses JSX
- JSX expressions
- JavaScript inside JSX
- JSX attributes
className- Self-closing elements
- Multiple elements
- Fragments
- JSX nesting
- Conditional rendering
- Rendering lists
- JavaScript expressions in JSX
- Common JSX mistakes
- JSX vs HTML
- JSX compilation
- JSX best practices
What Is JSX?
JSX stands for JavaScript XML.
It is a syntax extension that allows you to write markup that looks similar to HTML inside JavaScript.
Example:
const element = <h1>Hello World</h1>;
It looks like HTML:
<h1>Hello World</h1>
But JSX is being written inside JavaScript.
Why Does React Use JSX?
Without JSX, you can create React elements using JavaScript APIs.
For example:
const element = React.createElement("h1",null,"Hello World");
With JSX:
const element = <h1>Hello World</h1>;
JSX is much easier to read.
So JSX gives developers a convenient way to describe UI.
JSX Is Not HTML
This is a very important distinction.
JSX:
<h1>Hello</h1>
looks like HTML, but it is not HTML.
It is JavaScript syntax that gets transformed into React element creation instructions.
Conceptually:
JSX↓Transformation↓JavaScript↓React↓UI
JSX Inside a Functional Component
The most common use is inside a component:
function Welcome() {return (<h1>Welcome to React</h1>);}
The component is JavaScript.
The returned markup is JSX.
JSX Must Be Returned
For example:
function Greeting() {return <h1>Hello</h1>;}
The JSX is returned by the component.
JSX Expressions
One of the most powerful JSX features is the ability to insert JavaScript expressions using {}.
Example:
function Greeting() {const name = "Jagannath";return (<h1>Hello, {name}</h1>);}
Result:
Hello, Jagannath
The {name} is a JavaScript expression embedded inside JSX.
Curly Braces {}
Curly braces tell JSX:
Evaluate this as JavaScript.
Example:
const age = 25;function User() {return (<p>Age: {age}</p>);}
You can also perform calculations:
function Price() {const price = 5000;const discount = 500;return (<p>Final price: ₹{price - discount}</p>);}
Result:
Final price: ₹4500
What Can Go Inside {}?
You can use JavaScript expressions.
For example:
{name}
{price * 2}
{user.name}
{isLoggedIn ? "Logout" : "Login"}
{items.length}
Expressions vs Statements
This distinction is important.
An expression produces a value:
{price * 2}
A ternary is also an expression:
{isLoggedIn ? "Logout" : "Login"}
But a statement such as:
if (isLoggedIn) {// ...}
cannot be placed directly inside JSX curly braces like this:
// ❌ Not valid<div>{if (isLoggedIn) {// ...}}</div>
Instead, use JavaScript before the return:
function UserStatus({ isLoggedIn }) {if (isLoggedIn) {return <p>Welcome!</p>;}return <p>Please log in.</p>;}
Or use a ternary:
function UserStatus({ isLoggedIn }) {return (<p>{isLoggedIn? "Welcome!": "Please log in."}</p>);}
JSX Attributes
JSX supports attributes that look similar to HTML attributes.
Example:
<imgsrc="/logo.png"alt="Company logo"/>
You can also use JavaScript expressions:
const imageUrl = "/logo.png";<imgsrc={imageUrl}alt="Company logo"/>
Notice:
src={imageUrl}
instead of:
src="imageUrl"
The first evaluates the JavaScript variable.
The second is simply the text "imageUrl".
String Attributes
You can use quotes for string values:
<h1 className="title">React</h1>
Here "title" is a string.
JavaScript Attribute Values
Use curly braces for JavaScript:
const className = "title";<h1 className={className}>React</h1>
You can also write:
<imgsrc={imageUrl}alt={imageDescription}/>
className Instead of class
In HTML:
<div class="container">
In JSX:
<div className="container">
React uses:
className
rather than:
class
Example:
function Card() {return (<div className="card"><h2>React</h2></div>);}
Why className?
Because class has special meaning in JavaScript syntax.
JSX uses JavaScript-compatible property naming.
Therefore:
className
is the standard JSX attribute.
Other JSX Attribute Differences
Some HTML attributes use different names in JSX.
Examples:
| HTML | JSX |
|---|---|
class | className |
for | htmlFor |
tabindex | tabIndex |
onclick | onClick |
React generally follows JavaScript-style property naming conventions.
Event Attributes
HTML:
<button onclick="save()">
JSX:
<button onClick={handleSave}>Save</button>
Notice:
onclick↓onClick
And the handler is provided as JavaScript:
onClick={handleSave}
Don't Call the Event Handler Immediately
Usually:
<button onClick={handleClick}>Click</button>
Not:
<button onClick={handleClick()}>Click</button>
The first gives React the function to call when the event happens.
The second calls the function during rendering.
If you need arguments, use a function:
<buttononClick={() => handleDelete(id)}>Delete</button>
JSX Requires Proper Closing Tags
HTML can sometimes tolerate omitted closing tags.
JSX is stricter.
Correct:
<p>Hello</p>
Correct:
<div>Content</div>
Incorrect:
<p>Hello
JSX expects properly structured markup.
Self-Closing Elements
Elements without children can be self-closing.
Correct:
<img src="/logo.png" alt="Logo" />
Correct:
<input type="text" />
Correct:
<Component />
Notice the /:
/>
JSX Must Have One Root
Traditionally, JSX returned by a component needs a single enclosing structure.
This is problematic:
function App() {return (<h1>Hello</h1><p>Welcome</p>);}
There are two sibling elements without a common parent.
You can wrap them:
function App() {return (<div><h1>Hello</h1><p>Welcome</p></div>);}
Or use a Fragment.
React Fragments
A Fragment lets you group elements without adding an extra DOM element.
function App() {return (<><h1>Hello</h1><p>Welcome</p></>);}
The shorthand:
<></>
represents a Fragment.
Explicit Fragment Syntax
You can also write:
import { Fragment } from "react";function App() {return (<Fragment><h1>Hello</h1><p>Welcome</p></Fragment>);}
The shorthand is usually more convenient.
Why Use Fragments?
Suppose you have:
<div><h1>Hello</h1><p>Welcome</p></div>
The extra <div> becomes part of the DOM.
With:
<><h1>Hello</h1><p>Welcome</p></>
there is no additional wrapper element.
This can be useful when the DOM structure matters.
JSX Nesting
JSX elements can be nested.
function Profile() {return (<section><h1>Profile</h1><div><h2>Student</h2><p>React Developer</p></div></section>);}
The hierarchy is:
section├── h1└── div├── h2└── p
JSX Can Contain Components
JSX isn't limited to HTML elements.
You can write:
function Header() {return <header>Header</header>;}function App() {return (<><Header /><main><h1>Home</h1></main></>);}
Here:
<Header />
is a React component.
JSX Is Case-Sensitive
This:
<CourseCard />
is different from:
<courseCard />
React uses capitalization to distinguish custom components from intrinsic HTML elements.
Use:
<CourseCard />
for React components.
JSX and JavaScript Variables
You can display variables:
function Profile() {const name = "Rahul";const course = "React";return (<div><h2>{name}</h2><p>{course}</p></div>);}
JSX and Objects
You can access object properties:
function User() {const user = {name: "Rahul",age: 25};return (<div><h2>{user.name}</h2><p>{user.age}</p></div>);}
JSX and Arrays
You can render arrays using JavaScript methods.
function Courses() {const courses = ["React","Java","Spring Boot"];return (<ul>{courses.map(course => (<li key={course}>{course}</li>))}</ul>);}
The important pattern is:
array↓map()↓JSX elements
JSX and Conditional Rendering
You can use the ternary operator:
function Status({ loggedIn }) {return (<div>{loggedIn? <p>Welcome!</p>: <p>Please log in.</p>}</div>);}
Or:
function Status({ loggedIn }) {return (<div>{loggedIn && <p>Welcome!</p>}</div>);}
The && pattern is useful when you only need to show something when a condition is true.
JSX Comments
JavaScript comments:
// comment
Inside JSX, comments need curly braces:
function App() {return (<div>{/* This is a JSX comment */}<h1>Hello</h1></div>);}
Don't write:
<!-- comment -->
That's an HTML comment, not JSX syntax.
JSX and Inline Styles
JSX allows style objects.
HTML:
<div style="color: red;">
JSX:
<div style={{ color: "red" }}>Hello</div>
Why two curly braces?
{ → JavaScript expression{ ... } → JavaScript object}
So:
style={{ color: "red" }}
means:
JSX expression↓JavaScript object
CSS Property Names
Because styles are JavaScript objects, CSS properties generally use camelCase.
CSS:
background-color: red;font-size: 20px;
JSX style object:
style={{backgroundColor: "red",fontSize: "20px"}}
JSX Boolean Attributes
Some properties can be expressed as booleans.
For example:
<button disabled>Save</button>
This means:
disabled={true}
You can also use:
<button disabled={isDisabled}>Save</button>
JSX null
Sometimes you don't want to render anything.
You can return:
return null;
For example:
function AdminPanel({ isAdmin }) {if (!isAdmin) {return null;}return <div>Admin Panel</div>;}
JSX Rendering of Values
React can render many JavaScript values.
For example:
<p>{name}</p>
Strings and numbers are commonly rendered.
Be careful with values such as objects:
const user = {name: "Rahul"};
This is not generally something you render directly:
<div>{user}</div>
Instead:
<div>{user.name}</div>
or transform the data appropriately.
JSX and undefined / null
Values such as:
nullundefinedfalse
are generally rendered as no visible content when used as JSX children.
This is useful for conditional rendering.
For example:
{isLoading && <p>Loading...</p>}
When isLoading is false, the expression doesn't produce visible UI.
JSX Expressions Can Call Functions
For example:
function formatName(name) {return name.toUpperCase();}function User() {return (<h1>{formatName("Rahul")}</h1>);}
Result:
RAHUL
Keep Complex Logic Outside JSX
This is technically possible:
<div>{users.filter(user => user.active).sort(...).map(...)}</div>
But if the expression becomes difficult to understand, move the logic outside the JSX.
For example:
function UserList({ users }) {const activeUsers =users.filter(user => user.active);return (<ul>{activeUsers.map(user => (<li key={user.id}>{user.name}</li>))}</ul>);}
This is easier to read.
JSX Attribute Expressions
Expressions can also be used in attributes:
function Avatar({ user }) {return (<imgsrc={user.avatar}alt={user.name}/>);}
Here:
user.avatar
and:
user.name
are JavaScript expressions.
Dynamic Class Names
A common pattern:
function Button({ active }) {return (<buttonclassName={active? "button active": "button"}>Save</button>);}
Or:
const className = active? "button active": "button";return (<button className={className}>Save</button>);
JSX and Accessibility
JSX makes it easy to use semantic HTML:
<button>Save</button>
<label htmlFor="email"></label><inputid="email"type="email"/>
Notice:
htmlFor
instead of HTML's:
for
JSX and aria-* Attributes
ARIA attributes can be written using their standard hyphenated names.
For example:
<buttonaria-label="Close">×</button>
These attributes are important for accessible interfaces.
JSX and data-* Attributes
You can also use:
<div data-testid="course-card">React</div>
or custom data attributes:
<div data-course-id="123">React</div>
JSX Compilation
You write:
const element = (<h1>Hello</h1>);
A build tool transforms JSX into JavaScript that React can work with.
Modern React tooling uses the JSX transform during the build process.
Conceptually:
JSX↓Babel / compiler / build tool↓JavaScript↓React runtime
With Vite, this transformation is integrated into the development/build pipeline.
JSX Is Not Required
React can technically be used without JSX.
For example:
const element = React.createElement("h1",null,"Hello");
But JSX is generally preferred because it makes UI structure much easier to read.
JSX vs HTML
| HTML | JSX |
|---|---|
class | className |
for | htmlFor |
onclick | onClick |
| Attribute strings | Can use JavaScript expressions |
| HTML comments | JSX comments |
| Can be more forgiving | More syntax rules |
| Browser parses it directly | Build tooling transforms it |
JSX vs JavaScript
JSX:
const element = (<h1>Hello</h1>);
JavaScript without JSX:
const element = React.createElement("h1",null,"Hello");
JSX gives us a much more readable representation of UI.
JSX Is Declarative
Consider:
<h1>Welcome</h1>
You are describing:
The UI should contain a heading with this content.
You aren't manually telling the browser:
Create an h1Set its textFind the DOMAppend the nodeUpdate it later
React handles the UI update process.
This is part of React's declarative programming model.
JSX and Component Composition
JSX makes component composition very readable.
function App() {return (<Layout><Header /><Sidebar /><MainContent /><Footer /></Layout>);}
You can almost read the UI hierarchy directly from the code.
JSX Children
Components can contain content:
<Card><h2>React</h2><p>Learn React.</p></Card>
The content between:
<Card>...</Card>
is passed to the component as children.
For example:
function Card({ children }) {return (<article>{children}</article>);}
This is an extremely important JSX and composition pattern.
Nested JSX Components
You can compose multiple layers:
<Layout><Header /><main><CourseList><CourseCard /><CourseCard /></CourseList></main><Footer /></Layout>
This creates a component hierarchy directly through JSX.
JSX Formatting
JSX can be formatted across multiple lines:
function CourseCard() {return (<article className="course-card"><h2>React Fundamentals</h2><p>Learn modern Reactfrom the basics.</p><button>Start Learning</button></article>);}
Good formatting makes JSX much easier to maintain.
JSX and Prettier
Most modern React projects use a formatter such as Prettier.
It can automatically format:
<button className="primary" onClick={handleClick}>Save</button>
into a readable structure when lines become long.
Consistent formatting isn't just cosmetic—it makes code reviews and maintenance easier.
Common Mistake: Using class
Incorrect:
<div class="container">
Correct:
<div className="container">
Common Mistake: Forgetting Self-Closing Tags
Incorrect:
<img src="/logo.png">
Correct:
<img src="/logo.png" />
Common Mistake: Multiple Root Elements
Incorrect:
return (<h1>Hello</h1><p>Welcome</p>);
Correct:
return (<><h1>Hello</h1><p>Welcome</p></>);
Common Mistake: Using HTML Comments
Incorrect:
<!-- Header -->
Correct:
{/* Header */}
Common Mistake: Forgetting {}
Suppose:
const name = "Rahul";
Incorrect:
<h1>name</h1>
This displays:
name
Correct:
<h1>{name}</h1>
This displays:
Rahul
Common Mistake: Putting Statements Inside JSX
Incorrect:
<div>{if (loggedIn) {return "Welcome";}}</div>
Use:
<div>{loggedIn ? "Welcome" : "Please login"}</div>
or move the logic outside the JSX.
Common Mistake: Calling Event Handlers
Usually incorrect:
<button onClick={handleClick()}>Save</button>
Correct:
<button onClick={handleClick}>Save</button>
With arguments:
<button onClick={() => handleClick(id)}>Save</button>
Common Mistake: Confusing Strings and Expressions
Compare:
<img src="imageUrl" />
and:
<img src={imageUrl} />
The first means:
Use the literal string "imageUrl"
The second means:
Evaluate the variable imageUrl
A Complete JSX Example
function CourseCard({title,instructor,price,isAvailable}) {return (<article className="course-card"><h2>{title}</h2><p>Instructor: {instructor}</p><p>Price: ₹{price}</p>{isAvailable ? (<button>Enroll Now</button>) : (<p>Currently unavailable</p>)}</article>);}
This example demonstrates:
JSX+Expressions+Props+Attributes+Conditional rendering+Components
Practical Example: Product Card
Let's create a more realistic JSX component.
function ProductCard({image,name,price,inStock}) {return (<article className="product-card"><imgsrc={image}alt={name}/><h2>{name}</h2><p>₹{price}</p>{inStock && (<span>In Stock</span>)}<buttondisabled={!inStock}>{inStock? "Add to Cart": "Out of Stock"}</button></article>);}
Notice how JavaScript and markup work together naturally.
JSX Mental Model
The most useful mental model is:
JSX│┌──────────┴──────────┐│ │UI Structure JavaScript Expressions│ ││ │└──────────┬──────────┘↓React Element↓React↓UI
JSX is essentially the bridge between your JavaScript logic and your UI structure.
JSX Cheat Sheet
Basic element
<h1>Hello</h1>
Variable
<h1>{name}</h1>
Expression
<p>{price * 2}</p>
Attribute
<img src={imageUrl} />
Class
<div className="card">
Event
<button onClick={handleClick}>
Conditional
{isLoggedIn && <Profile />}
Ternary
{isLoggedIn ? <Profile /> : <Login />}
List
{items.map(item => (<li key={item.id}>{item.name}</li>))}
Fragment
<><Header /><Main /></>
Comment
{/* Comment */}
Self-closing
<img />
Interview questions & answers
Interview preparation
6 questions grouped by difficulty — expand any card for a model answer and follow-up probe.
Beginner
1What Is JSX?
BeginnerModel answer
JSX is a syntax extension for JavaScript commonly used with React to describe UI using an HTML-like syntax.
JSX isn't HTML; it is transformed into JavaScript representations that React can use to create and update the UI.
It also allows JavaScript expressions to be embedded using curly braces.
2Is JSX Mandatory in React?
BeginnerModel answer
No.
createElement directly.
However, JSX is generally preferred because it makes UI structure significantly easier to read and maintain.
Intermediate
3Why Does JSX Use className?
IntermediateModel answer
JSX uses JavaScript-style property naming, so the HTML class attribute is represented as className.
This avoids conflicts with JavaScript syntax and matches the property naming convention used by React.
4What Are Curly Braces Used For?
IntermediateModel answer
Curly braces in JSX allow JavaScript expressions to be embedded within markup.
They can contain values, calculations, function calls, property access, conditional expressions, and other JavaScript expressions.
5Can You Use if Directly Inside JSX?
IntermediateModel answer
Generally, no.
if is a statement, while JSX curly braces expect an expression.
Move the logic outside JSX or use an expression such as a ternary.
Advanced
6Why Do JSX Elements Need to Be Properly Closed?
AdvancedModel answer
JSX uses a stricter syntax structure than HTML because it is part of JavaScript code.
Elements without children must be explicitly self-closed, for example img with a closing slash.
Important JSX Rules to Remember
If you remember nothing else from this lesson, remember these:
1. JSX looks like HTML but is JavaScript syntax.2. Use {} for JavaScript expressions.3. Use className instead of class.4. Close every JSX element.5. Self-close elements with no children.6. Use a common parent or Fragment for siblings.7. Use PascalCase for React components.8. Use camelCase for most JSX properties/events.9. Use {/* */} for JSX comments.10. Keep complex logic outside the JSX when it hurts readability.
Practice Exercise
Create a StudentCard component that accepts:
namecourseprogressisActive
Usage:
<StudentCardname="Rahul"course="React"progress={75}isActive={true}/>
It should render:
RahulReactProgress: 75%Active
Bonus
If isActive is false, show:
Inactive
Possible solution
function StudentCard({name,course,progress,isActive}) {return (<article className="student-card"><h2>{name}</h2><p>Course: {course}</p><p>Progress: {progress}%</p><p>{isActive? "Active": "Inactive"}</p></article>);}
The most important idea is:
JSX lets you describe what your React UI should look like while still using JavaScript expressions and logic.
Think of JSX as:
JavaScript+UI Markup↓JSX↓React Elements↓React↓Browser UI
Once JSX becomes comfortable, the next major step is understanding JSX expressions and embedding JavaScript in JSX in depth, because that is what makes React components dynamic rather than static.