1. Introduction đ
JSX (JavaScript XML) is one of the defining features of React development. It allows you to write markup that looks like HTML directly inside your JavaScript code. This tutorial covers everything from basic syntax to advanced rules, common mistakes, and how JSX is compiled behind the scenes.
Information
2. What is JSX? đ¤
JSX is a syntax extension for JavaScript that allows you to write HTML-like structures within your JavaScript code. It is not valid JavaScript on its own â it must be compiled into regular JavaScript function calls before it can run in a browser.
A Simple JSX Example
const element = <h1>Hello, world! đ</h1>;Behind the scenes, this JSX is transformed into a call to React.createElement() (or a similar function), which produces a plain JavaScript object describing the UI.
3. Why JSX? đĄ
React was designed around the idea that rendering logic and UI markup are inherently coupled â so instead of separating them into different files, JSX lets you keep them together in one cohesive unit: the component.
- Readability: Markup structure is immediately visible alongside the logic that drives it.
- Type Safety: With TypeScript, JSX enables compile-time checking of props and elements.
- Tooling Support: Enables syntax highlighting, autocompletion, and error checking in editors.
- Familiarity: Its HTML-like syntax makes it approachable for developers with web backgrounds.
Note
4. JSX Syntax đ
JSX combines the structure of HTML with the power of JavaScript expressions, all within curly braces {}.
Basic JSX Syntax
const name = "Alice";
const greeting = (
<div className="greeting">
<h1>Hello, {name}!</h1>
<p>Welcome to React.</p>
</div>
);- Tags resemble HTML elements (<div>, <h1>, etc.).
- Curly braces {} embed JavaScript expressions.
- Attributes use camelCase instead of HTML's lowercase convention (e.g., className instead of class).
5. Writing Your First JSX âī¸
App.jsx
function App() {
const user = "Developer";
return (
<div>
<h1>Hello, {user}! đ</h1>
<p>This is your first JSX component.</p>
</div>
);
}
export default App;Tip
6. JSX Rules đ
JSX looks like HTML but follows stricter rules since it must ultimately compile into valid JavaScript function calls.
- Return a single root element (or a Fragment) from a component.
- Close every tag, including self-closing elements like <img /> and <br />.
- Use camelCase for most attribute names (e.g., onClick, tabIndex).
- Use className instead of class, and htmlFor instead of for.
- JavaScript reserved words cannot be used as-is for certain attributes.
Warning
7. Expressions in JSX đ§Ž
Any valid JavaScript expression can be embedded inside JSX using curly braces. This includes variables, function calls, arithmetic, ternaries, and more.
Code Snippet
const price = 49.99;
const isDiscounted = true;
const element = (
<p>
Price: ${isDiscounted ? (price * 0.9).toFixed(2) : price}
</p>
);Caution
8. Embedding JavaScript in JSX đ
JSX allows seamless embedding of variables, function calls, and even other JSX elements.
Code Snippet
function formatDate(date) {
return date.toLocaleDateString();
}
function Article({ title, publishedAt }) {
return (
<article>
<h2>{title}</h2>
<p>Published on {formatDate(publishedAt)}</p>
</article>
);
}| Expression Type | Example |
|---|---|
| Variables | {userName} |
| Function Calls | {formatDate(date)} |
| Arithmetic | {price * quantity} |
| Ternary Expressions | {isActive ? "Yes" : "No"} |
9. JSX Attributes đˇī¸
JSX attributes behave like HTML attributes but accept JavaScript expressions as values when wrapped in curly braces, instead of only string literals.
Code Snippet
const imageUrl = "https://example.com/photo.jpg";
const isDisabled = false;
const element = (
<div>
<img src={imageUrl} alt="Profile photo" width={200} />
<button disabled={isDisabled}>Submit</button>
</div>
);- String values use quotes: title="Hello".
- Expression values use curly braces: title={variable}.
- Boolean attributes can be shorthand: <input disabled /> implies disabled={true}.
10. HTML vs JSX âī¸
| Aspect | HTML | JSX |
|---|---|---|
| Class Attribute | class="box" | className="box" |
| Label For | for="name" | htmlFor="name" |
| Inline Styles | String: style="color:red" | Object: style={{ color: "red" }} |
| Event Attributes | Lowercase: onclick | camelCase: onClick |
| Self-Closing Tags | Optional: <img> | Required: <img /> |
| Comments | <!-- comment --> | {/* comment */} |
11. JSX Children đļ
Elements in JSX can contain children â nested elements, text, expressions, or a combination of all three.
Code Snippet
const element = (
<div>
Plain text child
<span>An element child</span>
{"An expression child"}
<p>Multiple <strong>nested</strong> children</p>
</div>
);Note
12. Self-Closing Elements â
Elements without children must be self-closed in JSX, unlike in HTML where this is often optional.
Code Snippet
// Correct
const good = (
<div>
<img src="photo.jpg" alt="A photo" />
<input type="text" />
<br />
<hr />
</div>
);
// Incorrect â will cause a compile error
// const bad = <img src="photo.jpg">;13. Nested Elements đĒ
JSX supports arbitrarily deep nesting, just like HTML, allowing you to compose complex UI structures from simple elements.
Code Snippet
const card = (
<div className="card">
<div className="card-header">
<h2>Card Title</h2>
</div>
<div className="card-body">
<p>Some <em>nested</em> content goes here.</p>
<ul>
<li>Item one</li>
<li>Item two</li>
</ul>
</div>
</div>
);Tip
14. Wrapping Multiple Elements đĻ
A component must return a single root element. To return multiple sibling elements, wrap them in a parent element or a Fragment.
Code Snippet
// â Invalid â multiple root elements
// function Invalid() {
// return (
// <h1>Title</h1>
// <p>Description</p>
// );
// }
// â
Valid â wrapped in a single parent
function Valid() {
return (
<div>
<h1>Title</h1>
<p>Description</p>
</div>
);
}15. React Fragments đ§Š
Fragments let you group multiple elements without introducing an extra DOM node â useful when you don't want an unnecessary wrapping <div>.
Code Snippet
import { Fragment } from 'react';
function List() {
return (
<Fragment>
<li>First item</li>
<li>Second item</li>
</Fragment>
);
}
// Shorthand syntax
function ListShorthand() {
return (
<>
<li>First item</li>
<li>Second item</li>
</>
);
}Tip
16. Comments in JSX đŦ
Comments inside JSX markup must be written as JavaScript expressions wrapped in curly braces, using the standard /* */ block comment syntax.
Code Snippet
function App() {
return (
<div>
{/* This is a comment inside JSX */}
<h1>Hello!</h1>
{
// Multi-line comments work too,
// but block comments are more common
}
</div>
);
}Caution
17. Conditional Rendering in JSX đ
JSX doesn't support if statements directly inside markup, but several JavaScript patterns achieve conditional rendering elegantly.
Code Snippet
function Status({ isOnline }) {
return <p>{isOnline ? "đĸ Online" : "đ´ Offline"}</p>;
}Code Snippet
function Notification({ hasUnread }) {
return (
<div>
{hasUnread && <span className="badge">New</span>}
</div>
);
}Code Snippet
function Profile({ user }) {
if (!user) {
return <p>Loading...</p>;
}
return <h1>Welcome, {user.name}!</h1>;
}Warning
18. Rendering Lists with JSX đ
Arrays of data can be transformed into lists of elements using JavaScript's .map() method.
Code Snippet
const fruits = ["Apple", "Banana", "Cherry"];
function FruitList() {
return (
<ul>
{fruits.map((fruit) => (
<li key={fruit}>{fruit}</li>
))}
</ul>
);
}19. Keys in JSX đ
When rendering lists, each element needs a unique key prop so React can efficiently track, reorder, and update items during reconciliation.
Code Snippet
const users = [
{ id: "u1", name: "Alice" },
{ id: "u2", name: "Bob" },
];
function UserList() {
return (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}Important
20. Event Handling in JSX đąī¸
JSX handles events using camelCase attribute names and passes a function reference rather than a string, as opposed to HTML's inline onclick="..." style.
Code Snippet
function Button() {
function handleClick() {
console.log("Button clicked!");
}
return <button onClick={handleClick}>Click Me</button>;
}
// Passing arguments with an arrow function
function DeleteButton({ id, onDelete }) {
return (
<button onClick={() => onDelete(id)}>Delete</button>
);
}Caution
21. Inline Styles in JSX đ¨
Inline styles in JSX use a JavaScript object instead of a CSS string, with property names written in camelCase.
Code Snippet
function Alert() {
const alertStyle = {
backgroundColor: "#fee2e2",
color: "#991b1b",
padding: "12px",
borderRadius: "8px",
};
return <div style={alertStyle}>Something went wrong!</div>;
}Note
22. Class Names in JSX đˇī¸
Since class is a reserved word in JavaScript, JSX uses className to apply CSS classes.
Code Snippet
function Card({ isActive }) {
return (
<div className={isActive ? "card card-active" : "card"}>
Card content
</div>
);
}Tip
23. Special JSX Attributes đ
| Attribute | Purpose |
|---|---|
| key | Helps React identify list items during reconciliation. |
| ref | Provides direct access to a DOM node or component instance. |
| dangerouslySetInnerHTML | Injects raw HTML directly, bypassing React's escaping. |
| children | Represents nested content passed between opening and closing tags. |
Danger
24. Escaping Values in JSX đĄī¸
React automatically escapes values embedded in JSX before rendering them, protecting your application against XSS injection attacks by default.
Code Snippet
const userInput = "<script>alert('hacked')</script>";
// Safe â React escapes this automatically, rendering it as plain text
const element = <p>{userInput}</p>;Success
25. JSX Compilation âī¸
Browsers cannot interpret JSX natively. A compiler such as Babel or SWC transforms JSX into standard JavaScript function calls before the code ever reaches the browser.
Before Compilation
const element = <h1 className="title">Hello!</h1>;After Compilation (Classic Runtime)
const element = React.createElement(
"h1",
{ className: "title" },
"Hello!"
);26. JSX Transform đ
React introduced a new JSX transform in React 17 that removes the need to manually import React in every file that uses JSX.
Code Snippet
import React from 'react';
const element = React.createElement("h1", null, "Hello!");Code Snippet
import { jsx as _jsx } from 'react/jsx-runtime';
const element = _jsx("h1", { children: "Hello!" });Information
27. JSX Best Practices đ
- Keep JSX readable by extracting complex logic into variables or helper functions before the return statement.
- Always provide a stable, unique key when rendering lists.
- Prefer Fragment over unnecessary wrapper <div> elements.
- Break large components into smaller, focused ones instead of deeply nesting JSX.
- Use self-closing tags consistently for elements without children.
- Avoid inline object/array literals in props when they cause unnecessary re-renders in performance-sensitive components.
28. Common JSX Mistakes đĢ
- Forgetting to close self-closing tags like <img> or <input>.
- Returning multiple root elements without a wrapping Fragment or parent element.
- Using class instead of className.
- Passing a string to style instead of an object.
- Using array index as a key in dynamic lists.
- Calling event handlers immediately, e.g. onClick={handleClick()}, instead of passing a reference.
Danger
29. Frequently Asked Questions â
Question
Answer
Question
Answer
Question
Answer
30. Summary đ
JSX bridges the gap between JavaScript logic and UI markup, offering a readable, expressive syntax that compiles down to plain JavaScript function calls. Understanding its rules â from self-closing tags and Fragments to keys and event handling â is essential for writing clean, maintainable React components.