JSX
What is JSXβ
JSX is an extension for JavaScript used in React. JSX lets you write HTML-like code inside JavaScript. This allows us to describe what a component renders with a structure that is familiar to web developers - HTML. React compiles our JSX into JavaScript calls to create elements and render them on the page.
For example, we created a Greeting component.
function Greeting() {
return (
<h1>Good morning!</h1>
)
}
export default Greeting;
This looks like HTML that is returned by our JavaScript function. However, this is actually JSX. React compiles it into something like:
React.createElement('h1', null, 'Good morning!);
WooHoo!! We didn't have to write the DOM instructions - React handles that π.
Why JSXβ
JSX makes your UI:
- declarative - you describe what you want to render, React handles the DOM
- components - you build complex UIs from small, reusable components
- integrated with logic - it's JavaScript, so loops, conditionals, variables, ... all our programmer tools work
JSX is not HTML, but a JavaScript syntax that looks like HTML β designed to describe UI in a familiar, readable way inside React components.
Rules of JSXβ
JSX is stricter than HTML. This section contains three important rules to remember when writing JSX. Examples of each are included.
1. Return a single root elementβ
Components must return a single root element.
To return multiple elements from a component, wrap them with a single parent tag.
You can add <div> </div> tags, or just <> </>
Here is an example component where we have more than one element to render, a heading and a paragraph. JSX requires
that they be wrapped as a single component. We can wrap them in <div> </div> tags:
const DoubleGreeting = function() {
return (
<div>
<h1>Good morning!</h1>
<p>Glad you are here.</p>
</div>
)
}
export default DoubleGreeting;
Use the DoubleGreeting component like:
...
This is my double greeting: <DoubleGreeting />
...
Or, we can wrap them with the shorthand <> </>:
const DoubleGreeting = function() {
return (
<>
<h1>Good morning!</h1>
<p>Glad you are here.</p>
</>
)
}
export default DoubleGreeting;
Use DoubleGreeting as:
...
This is my double greeting: <DoubleGreeting />
...
Either syntax will produce:
Why can components only return a single element? JSX is transformed to JavaScript objects. You can't return two objects from a function without wrapping them into an array. So, you also can't return two JSX tags without wrapping them into another tag.
2. Close all tagsβ
In HTML, the / is not required to close the <img> tag. However, in JSX, all tags must be
closed, either <>... </> or <..../> if a singleton tag.
const Profile = () => (
<img
src="/img/react-buzz-lightyear.png"
alt="Buzz Lightyear"
width="100px"
/>
)
export default Profile;
3. Attributes use camelCaseβ
In JSX, attributes use camelCase. For example, className in JSX instead
of class as in HTML.
We use two attributes in this component that incorporates an event handler.
- use
classNameinstead of class - use
onClickinstead of onclick
export default function AlertThis() {
const handleClick = () => {
alert('Alert Issued!');
};
return (
<button className="btn" onClick={handleClick}>
ALERT
</button>
);
}
We can use the AlertThis component in a component:
...
Click this <AlertThis /> to issue an alert message!
...
... and it is rendered as:
Note that the event handler is part of the function component and sits at the top of the functional component before the JSX.
JavaScript Expressions in {}β
In JSX, the curly braces are used to embed JavaScript expressions inside your markup.
This allows you to embed values, logic, and function calls directly into your HTML-like markup.
Curly braces {} tell the transpiler to evaluate what is in the curly braces as
JavaScript.
This example renders the current value of a variable:
const name = "Joe";
return <h1>Hello, {name}!</h1>;
{name} evaluates to "Joe", so the return becomes:
<h1>Hello, Joe!</h1>
Expressions vs. statementsβ
Expressions always produce a value. Examples:
2 + 2 // β 4
user.name // β "Bob"
isLoggedIn ? "Welcome" : "Please sign in" // β "Welcome"
Statements perform an action but do not directly produce a value you can use inline. A statement executes, but it doesnβt itself evaluate to a usable result. Examples:
if (x > 0) { ... }
for (let i = 0; i < 5; i++) { ... }
return value;
JSX allows only expressions in the {}, not full statements.
Conditional expressionsβ
JavaScript expressions, not statements, are allowed inside the curly braces. Thatβs why the conditional (ternary) operator is so handyβit gives you a value in-line where a statement like if or if/else cannot.
To break a conditional into an allowable expression, the ternary operator provides a
solution as in this example:
const Welcome = () => {
const isLoggedIn = true;
return (
<div>
{ isLoggedIn ? ( <p>Welcome!</p> ) : ( <p>Please login!</p> )}
</div>
);
}
export default Welcome;
The conditional statements in the example below are valid because they are just part of the JavaScript function and
outside the JSX markup. You can include any valid JavaScript/TypeScript in the function
component. However, only JavaScript expressions can be evaluated in the {} of the JSX.
const Welcome = () => {
const isLoggedIn = true;
let message;
if (isLoggedIn) {
message = <p>Welcome!</p>;
} else {
message = <p>Please login!</p>;
}
return (
<div>
{message}
</div>
);
};
export default Welcome;
map to generate listβ
For loops are not expressions, so cannot be used within JSX. However, we can use JavaScript map.
MDN JS Map Array To
map over an array of posts and display the title for each one. The posts are passed as part of the props parameter. See
the example below which uses map to generate a new list of titles wrapped in <li> </li> tags.
const ListPosts = ({ posts }) => {
const postItems = posts.map((post) => (
<li key={post.id}>{post.title}</li>
));
return (
<ul>
{postItems}
</ul>
);
};
export default ListPosts;
What's legal in {}β
| Expression Type | Example | Result |
|---|---|---|
| Variable | {name} | "Diane" |
| Math | {2 + 2} | 4 |
| Ternary condition | {isLoggedIn ? 'Welcome' : 'Sign in'} | Dynamic text |
| Function call | {getMessage()} | Whatever getMessage() returns |
| Array mapping | {items.map(item => <li>{item}</li>)} | Renders a list |
| String concat | {first + ' ' + last} | Full name string |
How JSX Differs from HTMLβ
Here's a recap of how JSX differs from basic HTML.
| Feature | JSX (in React) | HTML |
|---|---|---|
| Syntax Context | Written in JavaScript (.jsx, .tsx) files | Written in .html files |
| Attributes | Uses camelCase (className, onClick) | Uses HTML names (class, onclick) |
| JavaScript Expressions | Can embed JavaScript expressions inside curly braces {} | Cannot embed JS |
| Components | Supports custom components like <Greeting /> | Only standard HTML tags |
| Self-closing Tags | Required for empty tags (<img />) | Optional in HTML (<img>) |
Nested Componentsβ
React components can be combined and nested to create complex user interfaces. Below is an example
App component that renders multiple child components. To use the <Greeting /> and <Profile />
components we import them:
import Greeting from './Greeting'; // Assuming Greeting.tsx is in the same directory
import Profile from './Profile'; // Assuming Profile.tsx is in the same directory
function App() {
return (
<div className="m-12 flex h-[500px] flex-col items-center justify-center bg-green-400 text-center text-3xl p-12 md:p-14 lg:p-16 xl:p-20">
<DoubleGreeting />
<Profile />
<Profile />
<Profile />
</div>
);
}
In React, JSX is the syntax used to define the structure of the UI, and itβs what a component returns. Everything else in the component β including variables, logic, functions, conditionals, loops, β is written using standard JavaScript/TypeScript.
If a component was not the default export, use {} on import.
ie. import { Greeting } from ./Greeting';
