Back to React tutorials
Basic12 min read

JSX

Write UI with JSX syntax — expressions, attributes, fragments, and the rules that keep markup valid JavaScript.

JSX Is Syntax Sugar

JSX looks like HTML embedded in JavaScript but compiles to `React.createElement` calls (or JSX runtime imports in modern setups). The compiler handles transforming tags, attributes, and children into JavaScript objects describing UI.

Because JSX is JavaScript, you can embed expressions with `{}`, spread props, and use any valid expression as a child. You cannot use statements inside `{}` without wrapping in an IIFE — prefer computing values above the return.

  • Compiles to createElement or jsx runtime
  • Expressions in `{}`
  • Not a separate template language
const element = <h1 className="title">{user.name}</h1>;

Attributes and DOM Differences

JSX uses camelCase for attributes: `className` instead of `class`, `htmlFor` instead of `for`. Event handlers use camelCase: `onClick`, `onChange`. Pass functions, not strings.

Boolean attributes like `disabled` and `checked` work as expected. Custom data attributes use lowercase: `data-testid`. Style accepts an object with camelCase CSS properties, not a string — prefer CSS classes for maintainability.

  • className, htmlFor, camelCase events
  • Style as object, prefer classes
  • data-* attributes lowercase
<button className="btn" onClick={handleClick} disabled={isLoading}>
  Submit
</button>

Fragments and Multiple Roots

Components must return a single parent element — use Fragments (`<>...</>` or `<Fragment>`) to group siblings without adding DOM nodes. Fragments are essential for table rows, list groups, and layout-free composition.

React 19+ allows documents with multiple roots in some cases, but fragments remain the standard pattern for component return values that need sibling elements.

  • Single parent required per return
  • Fragments avoid extra DOM nodes
  • Short syntax `<>...</>`
return (
  <>
    <Header />
    <Main />
  </>
);

Conditional and List Rendering

Render conditionally with `&&`, ternary operators, or early returns. Choose readability — nested ternaries in JSX become hard to review. Extract complex conditions to variables or subcomponents.

Render lists with `map`, always providing a stable `key` prop from data IDs — never array index when order can change. Keys help React match items correctly during insert, delete, and reorder operations.

  • && and ternary for conditionals
  • map for lists with stable keys
  • Avoid index keys on reorderable lists
{items.map(item => (
  <li key={item.id}>{item.label}</li>
))}

Security and JSX

React escapes text interpolated in JSX by default, preventing XSS from string values. Never pass unsanitized HTML strings to `dangerouslySetInnerHTML` unless content is trusted or sanitized with a library like DOMPurify.

User-generated URLs in `href` attributes can enable javascript: protocol attacks — validate URLs before rendering links. Treat all external content as untrusted at the JSX boundary.

  • Default escaping prevents XSS
  • Avoid dangerouslySetInnerHTML
  • Validate user-provided URLs

Get In Touch


Ready to discuss your next project? Drop me a message.