JSX Deep Dive: Syntax, Logic Embedding, Gotchas

One of the key features of React is JSX (JavaScript XML), a syntax extension that allows us to write HTML-like code inside JavaScript. JSX makes React code more readable and expressive. However, to fully leverage it, it’s essential to understand its syntax, how logic can be embedded, and some common pitfalls developers encounter when using it.

In this module, we’ll explore:

  • What JSX is and how it works
  • Embedding JavaScript logic inside JSX
  • Common gotchas and best practices to avoid errors

What is JSX?

JSX is not a separate language. It’s a syntax extension for JavaScript that lets you write HTML-like code directly in JavaScript. This makes React components look more like the HTML you’re used to working with, but it’s still JavaScript under the hood.

For example, here’s a simple JSX expression:

const element = <h1>Hello, World!</h1>;

JSX gets compiled into JavaScript code by tools like Babel, transforming it into something like this:

const element = React.createElement('h1', null, 'Hello, World!');

The JSX syntax allows you to express the UI structure more clearly without manually calling React.createElement() for each DOM node.


JSX Syntax

Here are the essential syntax rules and features of JSX:

1. JSX is Expression Syntax

JSX is just syntactic sugar over React’s React.createElement() function. You can use JavaScript expressions inside JSX by enclosing them in curly braces {}.

const name = 'John';
const element = <h1>Hello, {name}!</h1>;

The expression inside {} will be evaluated and its result will be inserted into the JSX. This is how you embed dynamic content into the UI.

2. JSX Tags Must Be Closed

Unlike HTML, JSX tags must always be closed. If you’re using an empty tag (like <img /> or <input />), make sure to self-close it.

// Valid JSX
const imgElement = <img src="logo.png" alt="logo" />;

// Invalid JSX (missing closing tag)
const imgElement = <img src="logo.png" alt="logo">

3. JSX Attributes

JSX attributes are similar to HTML attributes but with a few differences:

  • class in HTML becomes className in JSX.
  • for in HTML becomes htmlFor in JSX.
  • You can pass dynamic values as well, similar to how JavaScript expressions work in JSX.
const button = <button className="btn-primary" htmlFor="inputId">Submit</button>;

Embedding JavaScript Logic in JSX

One of the most powerful features of JSX is its ability to embed JavaScript logic directly in the markup. You can use JavaScript expressions and control structures (like conditionals, loops) inside your JSX, but with certain syntax constraints.

1. Conditionals in JSX

You can use ternary operators for conditional rendering inside JSX. This is the most common approach to conditionally display elements:

const isLoggedIn = true;
const greeting = <h1>{isLoggedIn ? 'Welcome back!' : 'Please sign in'}</h1>;

Alternatively, short-circuit evaluation can be used for conditional rendering:

const showMessage = true;
const message = showMessage && <p>This is a conditional message</p>;

In this example, if showMessage is false, nothing will be rendered.

2. Loops in JSX (Rendering Lists)

To render lists of elements, you can use JavaScript’s .map() method. Ensure that each element in the list has a unique key prop to help React efficiently update the DOM.

const numbers = [1, 2, 3, 4, 5];
const numberList = (
<ul>
{numbers.map((number) => (
<li key={number}>{number}</li>
))}
</ul>
);

3. Function Calls and Expressions

You can also call functions inside JSX. However, remember that JSX can only evaluate expressions and cannot handle statements like if, for, or while.

function greetUser(name) {
return `Hello, ${name}`;
}

const element = <h1>{greetUser('John')}</h1>;

Common Gotchas in JSX

1. JSX is Case-Sensitive

JSX is case-sensitive. HTML elements are lowercase (<div />, <button />), but custom React components need to be capitalized.

// Correct
const MyComponent = () => <h1>Hello, World!</h1>;

// Incorrect
const myComponent = () => <h1>Hello, World!</h1>; // will not render

2. No class Attribute in JSX

As mentioned, class in HTML is replaced by className in JSX.

// Correct
const element = <div className="container"></div>;

// Incorrect
const element = <div class="container"></div>; // will cause an error

3. JSX Elements Need to Have One Parent Element

JSX elements must be wrapped in a single parent element. For example:

// Correct
const container = (
<div>
<h1>Hello</h1>
<p>Welcome to React</p>
</div>
);

// Incorrect
const container = (
<h1>Hello</h1>
<p>Welcome to React</p>
); // will throw an error

If you want to avoid unnecessary wrapping elements, React offers a Fragment shorthand (<>...</>) to group elements without introducing additional DOM nodes.

const container = (
<>
<h1>Hello</h1>
<p>Welcome to React</p>
</>
);

Best Practices for JSX

  • Always use className instead of class in JSX.
  • Always use htmlFor instead of for when working with form elements.
  • Use curly braces {} to embed JavaScript expressions within JSX.
  • Avoid side effects in JSX. Do not put imperative code (e.g., console.log(), or direct state mutations) inside JSX expressions.
  • Use fragments to avoid unnecessary wrapper divs and reduce DOM clutter.
  • Always ensure unique keys for list items to avoid rendering issues.

Summary

JSX is a powerful feature in React that allows you to write HTML-like code inside JavaScript. Understanding how to embed JavaScript logic and handle common pitfalls will help you write cleaner and more efficient code. In the next module, we will explore React Components: Functional vs Class-based, where you’ll learn how to define and manage components in React.