Welcome back, aspiring React developer! In Chapter 1, you set up your development environment and got a taste of what React is all about. Now, it’s time to dive into one of React’s most distinctive features: JSX.
JSX might look a bit unusual at first glance – like a mix of JavaScript and HTML. But don’t let its unique appearance intimidate you! By the end of this chapter, you’ll not only understand what JSX is and why React uses it, but you’ll also be comfortable writing your own JSX code to define your application’s user interface. We’ll explore how JSX allows us to build UI in a declarative and intuitive way, and peek behind the curtain to see how it works under the hood. This fundamental understanding is crucial for building any modern React application.
Ready to make friends with React’s special syntax? Let’s go!
What is JSX? Your UI Blueprint
At its heart, JSX (JavaScript XML) is a syntax extension for JavaScript. It allows you to write HTML-like markup directly within your JavaScript code. Think of it as a convenient and powerful way to describe what your UI should look like.
Why does React use it? Because it allows developers to keep their UI logic and markup in the same place, making components self-contained and easier to reason about. Instead of separating your HTML in one file, your JavaScript in another, and your CSS somewhere else, JSX lets you define your component’s appearance and behavior together. This leads to a more intuitive and declarative way of building user interfaces.
It’s important to remember that JSX is not HTML. While it looks very similar, it’s actually a special syntax that gets transformed into regular JavaScript. Browsers don’t understand JSX directly, which brings us to our next point.
JSX Under the Hood: The Magic of Transpilation
Since browsers don’t natively understand JSX, how does it work? This is where a tool called a transpiler comes into play. The most common transpiler used with React is Babel.
Before your React code runs in the browser, Babel takes your JSX code and converts it into standard JavaScript function calls – specifically, calls to React.createElement(). This function is what actually creates React “elements,” which are plain JavaScript objects that describe what you want to see on the screen.
Let’s look at a simple example to demystify this:
// Your JSX code
const element = <h1>Hello, React!</h1>;
Babel transforms this JSX into something like this:
// What Babel converts your JSX into
const element = React.createElement("h1", null, "Hello, React!");
See the magic? The React.createElement() function takes three main arguments:
- The type of HTML tag or component (e.g.,
"h1","div", or a customMyComponent). - An object containing any props (attributes) for the element (e.g.,
className,id). If there are no props,nullis used. - Any children of the element (e.g., text content, other
React.createElementcalls).
This transformation happens automatically behind the scenes when you’re using a modern build tool like Vite (which we set up in Chapter 1). You write the easy-to-read JSX, and Babel handles the conversion to browser-friendly JavaScript. Pretty neat, right?
Embedding JavaScript Expressions in JSX: The Curly Braces {}
One of the most powerful features of JSX is its ability to embed JavaScript expressions directly within your markup. This is how you make your UI dynamic! To embed a JavaScript expression, you simply wrap it in curly braces {}.
You can embed variables, function calls, arithmetic operations, and more.
Let’s explore some common scenarios:
1. Displaying Variables
const name = "Alice";
const greeting = <h1>Hello, {name}!</h1>;
// This will render: <h1>Hello, Alice!</h1>
2. Performing Simple Calculations
const sum = <p>2 + 3 = {2 + 3}</p>;
// This will render: <p>2 + 3 = 5</p>
3. Calling Functions
function formatUser(user) {
return user.firstName + ' ' + user.lastName;
}
const user = {
firstName: 'Jane',
lastName: 'Doe'
};
const userDisplay = <p>User: {formatUser(user)}</p>;
// This will render: <p>User: Jane Doe</p>
Important Rule: Inside {} in JSX, you can only put expressions, not statements.
- Expressions produce a value (e.g.,
1 + 1,name,myFunction(),true ? 'yes' : 'no'). - Statements perform an action but don’t produce a value (e.g.,
if (condition) {},for (let i = 0; i < 5; i++) {},const x = 5;).
If you need conditional logic or loops, you’ll typically use ternary operators, logical &&, or map over arrays outside the JSX or within a function that returns JSX. We’ll cover these patterns more in later chapters!
JSX Attributes: Styling and Properties
Just like HTML elements can have attributes (like class, src, alt), JSX elements can also have attributes. However, there are a few key differences you need to know:
1. className instead of class
In HTML, you use class to apply CSS classes. In JSX, you must use className. Why? Because class is a reserved keyword in JavaScript (used for defining classes!), and JSX is JavaScript.
<div className="my-stylish-div">
This div has a CSS class.
</div>
2. CamelCase for DOM Properties
Many HTML attributes become camelCase in JSX when they refer to DOM properties. For example, tabindex becomes tabIndex, and for (for labels) becomes htmlFor.
<label htmlFor="myInput">Enter your name:</label>
<input id="myInput" type="text" tabIndex="0" />
3. Inline Styles with JavaScript Objects
While using CSS classes with className is the preferred way to style in React, you can also apply inline styles using the style attribute. The style attribute expects a JavaScript object where property names are camelCase (e.g., backgroundColor instead of background-color) and values are strings.
<p style={{ color: 'blue', fontSize: '16px', backgroundColor: 'lightgray' }}>
This text is styled inline!
</p>
Notice the double curly braces: the outer {} indicates that we’re embedding a JavaScript expression, and the inner {} defines the JavaScript object for the styles.
4. Boolean Attributes
For boolean HTML attributes like disabled, checked, or readOnly, you can simply include the attribute name to set it to true. To set it to false, you can omit it or explicitly set it to {false}.
<button disabled>Click Me</button> {/* disabled is true */}
<input type="checkbox" checked={true} /> {/* checked is true */}
<input type="checkbox" checked={false} /> {/* checked is false */}
Self-Closing Tags and Children
In JSX, every element must be properly closed. This means:
- Self-closing tags: Elements that don’t have children (like
<img>,<input>,<br>) must be self-closed with a/before the closing angle bracket.<img src="logo.png" alt="Company Logo" /> <input type="text" /> - Paired tags: Elements that can have children (like
<div>,<p>,<h1>) must have both an opening and a closing tag.<div> <p>This is a paragraph inside a div.</p> </div>
What can be children of a JSX element?
- Text:
<div>Hello!</div> - Other JSX elements:
<div><p>Nested!</p></div> - JavaScript expressions that evaluate to a string, number, or an array of elements:(We’ll dive deeper into
const items = ['Apple', 'Banana', 'Cherry']; <ul> {items.map(item => <li key={item}>{item}</li>)} </ul>keywhen we cover lists in a later chapter, but it’s good practice to include it when rendering lists of elements.)
Step-by-Step Implementation: Writing Your First JSX
Let’s get hands-on! We’ll use the Vite project you set up in Chapter 1.
Open your project: Navigate to your project directory in your terminal and ensure your development server is running:
cd my-react-app # Or whatever you named your project npm run devOpen your browser to the address shown (usually
http://localhost:5173).Locate
App.jsx: In your project structure, findsrc/App.jsx. This is where we’ll be making our changes.Your
App.jsxmight look something like this initially (with some boilerplate removed for clarity):// src/App.jsx import './App.css' // We can ignore this for now function App() { return ( <> {/* Existing content or empty fragment */} <h1>Vite + React</h1> </> ) } export default AppThe
<>and</>are called Fragments. They let you group multiple elements without adding an extra node to the DOM, which is very handy!Create a Simple JSX Element: Let’s replace the existing
<h1>with our own simple greeting.- Delete the
<h1>Vite + React</h1>line. - Add the following inside the
returnstatement’sFragment:
// src/App.jsx import './App.css' function App() { return ( <> {/* New code starts here */} <h1>Hello from JSX!</h1> <p>This is my first React element.</p> {/* New code ends here */} </> ) } export default AppSave the file. Your browser should automatically refresh and display “Hello from JSX! This is my first React element.”
- Delete the
Embed a JavaScript Variable: Now, let’s make our greeting dynamic.
- Add a
constvariable before thereturnstatement in theAppfunction:
// src/App.jsx import './App.css' function App() { const userName = "Learner"; // New line return ( <> <h1>Hello, {userName}!</h1> {/* Modified line */} <p>This is my first React element.</p> </> ) } export default AppSave. You should now see “Hello, Learner!”
- Add a
Use Attributes (
classNameandstyle): Let’s apply some basic styling using bothclassNameandstyle.- First, open
src/App.cssand add a very simple CSS class:
/* src/App.css */ .highlight { color: purple; font-weight: bold; }- Now, modify
src/App.jsxto use this class and an inline style:
// src/App.jsx import './App.css' function App() { const userName = "Learner"; return ( <> <h1 className="highlight">Hello, {userName}!</h1> {/* Added className */} <p style={{ color: 'green', fontSize: '18px' }}> {/* Added style */} This text is styled with JSX attributes! </p> </> ) } export default AppSave both files. You should see “Hello, Learner!” in purple bold text, and the paragraph in green, larger text.
- First, open
Mini-Challenge: Your Dynamic Display
Alright, your turn! Let’s solidify your understanding of JSX with a small challenge.
Challenge:
- In your
src/App.jsxfile, create a new variable namedcurrentYearand set its value to the current year (e.g.,2026). - Create a new
<footer>element below your existing<p>tag. - Inside the
<footer>, display a copyright notice like “© 2026 My Awesome App”. Use yourcurrentYearvariable to display the year dynamically. - Apply an inline style to your
<footer>to give it atextAlignof'center'and acolorof'gray'.
Hint: Remember to use curly braces {} for embedding JavaScript expressions, and double curly braces {{}} for inline style objects!
What to Observe/Learn: You should see a centered, gray copyright notice at the bottom of your app, with the year dynamically pulled from your variable. This reinforces embedding variables and applying inline styles.
Common Pitfalls & Troubleshooting
As you start writing more JSX, you might encounter a few common hiccups:
classvs.className: This is probably the most frequent mistake for beginners coming from HTML. Always useclassNamein JSX. If you useclass, React will likely warn you in the console, and your styles might not apply correctly.- Returning Multiple Elements: A React component (or the
returnstatement in a function component) must return a single parent element. You can’t return two siblingdivs directly.- Incorrect:
// This will cause an error! function MyComponent() { return ( <h1>Hello</h1> <p>World</p> ); } - Correct (using a
div):function MyComponent() { return ( <div> <h1>Hello</h1> <p>World</p> </div> ); } - Correct (using a Fragment
<>...</>): This is often preferred as it doesn’t add an extradivto your HTML output.function MyComponent() { return ( <> <h1>Hello</h1> <p>World</p> </> ); }
- Incorrect:
- Using JavaScript Statements in
{}: Remember, only expressions go inside{}. You can’t putifstatements orforloops directly.- Incorrect:
{ if (condition) { <p>Conditional</p> } } // Error! - Correct (using a ternary operator for conditionals):
{ condition ? <p>Conditional</p> : null } - Correct (mapping over an array for lists):
<ul> {items.map(item => <li key={item}>{item}</li>)} </ul> - Correct (extracting logic to a helper function):
function renderContent() { if (condition) { return <p>Conditional</p>; } return null; } function MyComponent() { return ( <div> {renderContent()} </div> ); }
- Incorrect:
Always check your browser’s developer console for errors and warnings. React and Babel are quite good at giving helpful messages!
Summary
Phew! You’ve just mastered one of React’s core building blocks: JSX. Let’s quickly recap what you’ve learned:
- JSX is a JavaScript syntax extension that lets you write HTML-like markup directly within your JavaScript code.
- It provides a declarative way to describe your UI, making components self-contained and easy to understand.
- Browsers don’t understand JSX. Babel (a transpiler) converts your JSX into regular
React.createElement()calls before your code runs. - You can embed JavaScript expressions (variables, functions, calculations) into your JSX using curly braces
{}. - JSX uses
classNameinstead ofclassfor CSS classes, and camelCase for many other DOM attributes (e.g.,htmlFor). - Inline styles are applied using a JavaScript object within the
styleattribute (e.g.,<p style={{ color: 'blue' }}>). - All JSX elements must be properly closed, either self-closing (
<img />) or with a closing tag (<div></div>). - React components must return a single parent element, often achieved with a
<div>or a Fragment (<>...</>).
You’re now equipped to start defining the visual structure of your React applications! In the next chapter, we’ll take this understanding of JSX and combine it with the concept of components, props, and state to build truly dynamic and reusable UI elements. Get ready to build your first interactive React components!
References
- React.dev: Writing Markup with JSX
- React.dev: Conditional Rendering
- MDN Web Docs: Getting started with React - JSX
- BabelJS: What is Babel?
This page is AI-assisted and reviewed. It references official documentation and recognized resources where relevant.