05_JSX(syntax extension to JavaScript) - Maniconserve/React-Wiki GitHub Wiki
JSX stands for JavaScript XML. It is a syntax extension to JavaScript that lets you write HTML-like markup directly inside JavaScript code. JSX is not valid JavaScript on its own — it gets compiled by Babel into regular JavaScript before the browser runs it.
To understand why JSX exists, let's render a simple <h1>Hello, World!</h1> four different ways.
The traditional way. HTML lives in its own file.
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
</head>
<body>
<h1>Hello, World!</h1>
</body>
</html>
✅ Simple and readable.
❌ Static — you cannot dynamically change content without JavaScript.
JavaScript manipulates the HTML page by selecting elements and setting their content.
<!-- index.html -->
<body>
<div id="root"></div>
<script src="app.js"></script>
</body>
// app.js
const heading = document.createElement('h1');
heading.textContent = 'Hello, World!';
const root = document.getElementById('root');
root.appendChild(heading);
✅ Dynamic — content can change at runtime.
❌ Verbose and hard to manage as your UI grows. You are manually building the DOM piece by piece.
React provides a JavaScript function to create UI elements. No HTML file syntax needed.
// app.js
import React from 'react';
import ReactDOM from 'react-dom/client';
const heading = React.createElement('h1', null, 'Hello, World!');
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(heading);
React.createElement(type, props, ...children) takes:
-
type — the HTML tag as a string (
'h1','div', etc.) -
props — attributes like
{ className: 'title', id: 'main' }, ornullif none - children — the content inside the element
✅ Pure JavaScript — no special syntax required.
❌ Very hard to read and write for complex UIs. Deeply nested components become unmanageable quickly.
JSX lets you write HTML-like syntax directly in JavaScript. Babel compiles it into React.createElement() calls behind the scenes.
// app.jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
function App() {
return <h1>Hello, World!</h1>;
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
Under the hood, Babel transforms <h1>Hello, World!</h1> into:
React.createElement('h1', null, 'Hello, World!')
✅ Readable — looks like HTML, familiar to anyone who knows web development.
✅ Powerful — you can embed JavaScript expressions directly inside your markup.
✅ Industry standard for React development.
Use { } curly braces to inject any JavaScript expression inside JSX.
const name = 'Arjun';
const age = 22;
function App() {
return (
<div>
<h1>Hello, {name}!</h1>
<p>You are {age > 18 ? 'an adult' : 'a minor'}.</p>
</div>
);
}
JSX looks like HTML but it is not HTML. Because JSX is compiled into JavaScript, certain HTML attributes conflict with reserved JavaScript keywords. Here are the key differences:
Reason: class is a reserved keyword in JavaScript (used to define ES6 classes). Using class as an attribute name inside JSX would confuse the JavaScript parser.
// ❌ Wrong — 'class' is a JS keyword
<h1 class="title">Hello</h1>
// ✅ Correct
<h1 className="title">Hello</h1>
Reason: for is also a reserved keyword in JavaScript (used in for loops). It is renamed in JSX to avoid the conflict.
// ❌ Wrong
<label for="email">Email</label>
// ✅ Correct
<label htmlFor="email">Email</label>
JSX expressions must have one parent element. You cannot return two sibling elements side by side.
// ❌ Wrong — two root elements
return (
<h1>Hello</h1>
<p>Welcome</p>
);
// ✅ Option 1 — wrap in a div
return (
<div>
<h1>Hello</h1>
<p>Welcome</p>
</div>
);
// ✅ Option 2 — use a Fragment (renders no extra DOM element)
return (
<>
<h1>Hello</h1>
<p>Welcome</p>
</>
);
HTML allows some tags to be left unclosed (e.g., <br>, <img>). JSX requires every tag to be self-closed or explicitly closed.
// ❌ Wrong
<br>
<img src="photo.png">
<input type="text">
// ✅ Correct
<br />
<img src="photo.png" />
<input type="text" />
HTML event attributes are all lowercase. In JSX they are written in camelCase because JSX maps them to JavaScript DOM event properties.
// ❌ Wrong — HTML style
<button onclick="handleClick()">Click Me</button>
// ✅ Correct — JSX style
<button onClick={handleClick}>Click Me</button>
Common examples:
| HTML Attribute | JSX Equivalent |
|---|---|
| onclick | onClick |
| onchange | onChange |
| onsubmit | onSubmit |
| onmouseover | onMouseOver |
When you write JSX, Babel transforms it before the browser sees it:
You write:
function App() {
return (
<div className="container">
<h1>Hello, {name}</h1>
<button onClick={handleClick}>Click</button>
</div>
);
}
Babel compiles it to:
function App() {
return React.createElement(
'div',
{ className: 'container' },
React.createElement('h1', null, 'Hello, ', name),
React.createElement('button', { onClick: handleClick }, 'Click')
);
}
This is exactly why JSX rules exist — the output must be valid JavaScript.
Part of the React Project Wiki — see also: React Project Structure
# JSX — JavaScript Syntax Extension WikiJSX stands for JavaScript XML. It is a syntax extension to JavaScript that lets you write HTML-like markup directly inside JavaScript code. JSX is not valid JavaScript on its own — it gets compiled by Babel into regular JavaScript before the browser runs it.
To understand why JSX exists, let's render a simple <h1>Hello, World!</h1> four different ways.
The traditional way. HTML lives in its own file.
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
</head>
<body>
<h1>Hello, World!</h1>
</body>
</html>✅ Simple and readable.
❌ Static — you cannot dynamically change content without JavaScript.
JavaScript manipulates the HTML page by selecting elements and setting their content.
<!-- index.html -->
<body>
<div id="root"></div>
<script src="app.js"></script>
</body>// app.js
const heading = document.createElement('h1');
heading.textContent = 'Hello, World!';
const root = document.getElementById('root');
root.appendChild(heading);✅ Dynamic — content can change at runtime.
❌ Verbose and hard to manage as your UI grows. You are manually building the DOM piece by piece.
React provides a JavaScript function to create UI elements. No HTML file syntax needed.
// app.js
import React from 'react';
import ReactDOM from 'react-dom/client';
const heading = React.createElement('h1', null, 'Hello, World!');
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(heading);React.createElement(type, props, ...children) takes:
-
type — the HTML tag as a string (
'h1','div', etc.) -
props — attributes like
{ className: 'title', id: 'main' }, ornullif none - children — the content inside the element
✅ Pure JavaScript — no special syntax required.
❌ Very hard to read and write for complex UIs. Deeply nested components become unmanageable quickly.
JSX lets you write HTML-like syntax directly in JavaScript. Babel compiles it into React.createElement() calls behind the scenes.
// app.jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
function App() {
return <h1>Hello, World!</h1>;
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);Under the hood, Babel transforms <h1>Hello, World!</h1> into:
React.createElement('h1', null, 'Hello, World!')✅ Readable — looks like HTML, familiar to anyone who knows web development.
✅ Powerful — you can embed JavaScript expressions directly inside your markup.
✅ Industry standard for React development.
Use { } curly braces to inject any JavaScript expression inside JSX.
const name = 'Arjun';
const age = 22;
function App() {
return (
<div>
<h1>Hello, {name}!</h1>
<p>You are {age > 18 ? 'an adult' : 'a minor'}.</p>
</div>
);
}JSX looks like HTML but it is not HTML. Because JSX is compiled into JavaScript, certain HTML attributes conflict with reserved JavaScript keywords. Here are the key differences:
Reason: class is a reserved keyword in JavaScript (used to define ES6 classes). Using class as an attribute name inside JSX would confuse the JavaScript parser.
// ❌ Wrong — 'class' is a JS keyword
<h1 class="title">Hello</h1>
// ✅ Correct
<h1 className="title">Hello</h1>Reason: for is also a reserved keyword in JavaScript (used in for loops). It is renamed in JSX to avoid the conflict.
// ❌ Wrong
<label for="email">Email</label>
// ✅ Correct
<label htmlFor="email">Email</label>JSX expressions must have one parent element. You cannot return two sibling elements side by side.
// ❌ Wrong — two root elements
return (
<h1>Hello</h1>
<p>Welcome</p>
);
// ✅ Option 1 — wrap in a div
return (
<div>
<h1>Hello</h1>
<p>Welcome</p>
</div>
);
// ✅ Option 2 — use a Fragment (renders no extra DOM element)
return (
<>
<h1>Hello</h1>
<p>Welcome</p>
</>
);HTML allows some tags to be left unclosed (e.g., <br>, <img>). JSX requires every tag to be self-closed or explicitly closed.
// ❌ Wrong
<br>
<img src="photo.png">
<input type="text">
// ✅ Correct
<br />
<img src="photo.png" />
<input type="text" />HTML event attributes are all lowercase. In JSX they are written in camelCase because JSX maps them to JavaScript DOM event properties.
// ❌ Wrong — HTML style
<button onclick="handleClick()">Click Me</button>
// ✅ Correct — JSX style
<button onClick={handleClick}>Click Me</button>Common examples:
| HTML Attribute | JSX Equivalent |
|---|---|
onclick |
onClick |
onchange |
onChange |
onsubmit |
onSubmit |
onmouseover |
onMouseOver |
In HTML, inline styles are written as a CSS string. In JSX, they must be written as a JavaScript object with camelCased property names.
// ❌ Wrong — HTML string style
<h1 style="color: red; font-size: 24px;">Hello</h1>
// ✅ Correct — JavaScript object
<h1 style={{ color: 'red', fontSize: '24px' }}>Hello</h1>The outer
{ }injects JavaScript into JSX. The inner{ }is the object literal.
| HTML | JSX | Reason for Change |
|---|---|---|
class |
className |
class is a reserved JS keyword |
for |
htmlFor |
for is a reserved JS keyword |
onclick |
onClick |
JSX uses camelCase DOM properties |
style="color:red" |
style={{ color: 'red' }} |
Styles must be JS objects in JSX |
<br> |
<br /> |
All tags must be closed in JSX |
| Multiple root elements | Single root / Fragment | JSX compiles to one function call |
When you write JSX, Babel transforms it before the browser sees it:
You write:
function App() {
return (
<div className="container">
<h1>Hello, {name}</h1>
<button onClick={handleClick}>Click</button>
</div>
);
}Babel compiles it to:
function App() {
return React.createElement(
'div',
{ className: 'container' },
React.createElement('h1', null, 'Hello, ', name),
React.createElement('button', { onClick: handleClick }, 'Click')
);
}This is exactly why JSX rules exist — the output must be valid JavaScript.