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:

  1. The type of HTML tag or component (e.g., "h1", "div", or a custom MyComponent).
  2. An object containing any props (attributes) for the element (e.g., className, id). If there are no props, null is used.
  3. Any children of the element (e.g., text content, other React.createElement calls).

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:
    const items = ['Apple', 'Banana', 'Cherry'];
    <ul>
      {items.map(item => <li key={item}>{item}</li>)}
    </ul>
    
    (We’ll dive deeper into key when 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.

  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 dev
    

    Open your browser to the address shown (usually http://localhost:5173).

  2. Locate App.jsx: In your project structure, find src/App.jsx. This is where we’ll be making our changes.

    Your App.jsx might 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 App
    

    The <> and </> are called Fragments. They let you group multiple elements without adding an extra node to the DOM, which is very handy!

  3. 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 return statement’s Fragment:
    // 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 App
    

    Save the file. Your browser should automatically refresh and display “Hello from JSX! This is my first React element.”

  4. Embed a JavaScript Variable: Now, let’s make our greeting dynamic.

    • Add a const variable before the return statement in the App function:
    // 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 App
    

    Save. You should now see “Hello, Learner!”

  5. Use Attributes (className and style): Let’s apply some basic styling using both className and style.

    • First, open src/App.css and add a very simple CSS class:
    /* src/App.css */
    .highlight {
      color: purple;
      font-weight: bold;
    }
    
    • Now, modify src/App.jsx to 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 App
    

    Save both files. You should see “Hello, Learner!” in purple bold text, and the paragraph in green, larger text.

Mini-Challenge: Your Dynamic Display

Alright, your turn! Let’s solidify your understanding of JSX with a small challenge.

Challenge:

  1. In your src/App.jsx file, create a new variable named currentYear and set its value to the current year (e.g., 2026).
  2. Create a new <footer> element below your existing <p> tag.
  3. Inside the <footer>, display a copyright notice like “© 2026 My Awesome App”. Use your currentYear variable to display the year dynamically.
  4. Apply an inline style to your <footer> to give it a textAlign of 'center' and a color of '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:

  1. class vs. className: This is probably the most frequent mistake for beginners coming from HTML. Always use className in JSX. If you use class, React will likely warn you in the console, and your styles might not apply correctly.
  2. Returning Multiple Elements: A React component (or the return statement in a function component) must return a single parent element. You can’t return two sibling divs 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 extra div to your HTML output.
      function MyComponent() {
        return (
          <>
            <h1>Hello</h1>
            <p>World</p>
          </>
        );
      }
      
  3. Using JavaScript Statements in {}: Remember, only expressions go inside {}. You can’t put if statements or for loops 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>
        );
      }
      

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 className instead of class for CSS classes, and camelCase for many other DOM attributes (e.g., htmlFor).
  • Inline styles are applied using a JavaScript object within the style attribute (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


This page is AI-assisted and reviewed. It references official documentation and recognized resources where relevant.