Search IOCombats

Search challenges, guides, questions and articles

What Is JSX and Why Is It Used in React?

Beginner8 min interview
Skills tested:
Understanding that JSX is syntactic sugar for React.createElement callsKnowing what Babel (or the new React transform) does to JSX at build timeUnderstanding the rules: single root element, camelCase attributes, className vs classKnowing the difference between JSX expressions (single values) and JSX statementsExplaining the colocation advantage: markup and logic in one place

Advertisement

🧩 Scenario

JSX is the syntax used in every React component. Understanding what it compiles to is not just trivia: it explains the single-root rule, why component names must be uppercase, why attributes differ from HTML, and why only expressions (not statements) work inside curly braces. These constraints flow directly from JSX being a function call in disguise.

Architecture Walkthrough

JSX as Syntactic Sugar

JSX is not a language. It is a syntax extension that compiles to JavaScript function calls. Every JSX element is transformed by Babel (or the React compiler) into a call to React.createElement(type, props, ...children). The type argument is either a string for HTML elements or a reference to a component function for custom components. The props argument is an object of the element's attributes. Children are the remaining arguments.

This compilation step explains several JSX rules. Component names must start with an uppercase letter because JSX uses the case to determine whether type should be a string (lowercase, treated as an HTML element) or a variable reference (uppercase, treated as a React component). A lowercase <button> becomes React.createElement('button', ...). An uppercase <Button> becomes React.createElement(Button, ...) where Button is looked up in scope.

Expressions, Not Statements

Inside JSX curly braces, you can embed any JavaScript expression: variables, function calls, ternary operators, logical &&, template literals. You cannot embed statements such as if, for, or while. This is because the curly braces resolve to a value that becomes an argument to React.createElement. An if statement does not produce a value and cannot be used in that position.

For conditional rendering, use the ternary operator (condition ? <A /> : <B />) or short-circuit evaluation (condition && <A />). For lists, use array.map() which returns an expression (an array of elements).

The New JSX Transform

Before React 17, the Babel transform used React.createElement, which required React to be in scope in every file that used JSX. React 17 introduced a new JSX transform that imports a different internal function (jsx from react/jsx-runtime) automatically, removing the need to import React from 'react' in every component file.


Key Code Explained

// JSX
const element = (
  <button className="primary" onClick={handleClick} disabled={isLoading}>
    {isLoading ? 'Saving...' : 'Save'}
  </button>
);

// What Babel transforms it to (old transform):
const element = React.createElement(
  'button',
  {
    className: 'primary', // note: className not class
    onClick: handleClick,
    disabled: isLoading,
  },
  isLoading ? 'Saving...' : 'Save', // children
);

// New JSX transform (React 17+):
import { jsx as _jsx } from 'react/jsx-runtime';
const element = _jsx('button', {
  className: 'primary',
  onClick: handleClick,
  disabled: isLoading,
  children: isLoading ? 'Saving...' : 'Save',
});

// Why className, not class?
// 'class' is a reserved keyword in JavaScript.
// Since JSX is compiled to JS objects, the property name cannot be 'class'.
// React chose className to mirror the DOM property name (element.className).
// Similarly, 'for' becomes 'htmlFor' on <label>.

// Conditional rendering patterns inside JSX
function StatusBadge({ status, count }: { status: string; count: number }) {
  return (
    <div>
      {/* Ternary: for if/else */}
      <span>{status === 'active' ? 'Active' : 'Inactive'}</span>

      {/* Short-circuit &&: for "render if true" */}
      {count > 0 && <span className="badge">{count}</span>}

      {/* Mapping a list: returns an array of elements */}
      {['a', 'b', 'c'].map((tag) => (
        <span key={tag} className="tag">
          {tag}
        </span>
      ))}
    </div>
  );
}

// Self-closing tags: required for elements with no children
// HTML: <input type="text">
// JSX:  <input type="text" />  (trailing slash required for void elements)

// Fragments: render multiple siblings without a wrapper DOM node
function MultiReturn() {
  return (
    <>
      <h1>Title</h1>
      <p>Paragraph</p>
    </>
  );
}
// Compiles to: React.createElement(React.Fragment, null, h1_element, p_element)

The {count > 0 && <span>...</span>} pattern has a gotcha: if count is 0, the expression evaluates to 0 which React renders as the text "0". To avoid this, use a boolean: {count > 0 && <span>...</span>} already produces a boolean on the left side (true or false), but if count is the direct left operand, use {!!count && <span>...</span>} or {count > 0 && ...} explicitly.


Tradeoffs

AspectJSXReact.createElement directly
ReadabilityHigh (resembles the output structure)Low (deeply nested function calls)
Learning curveRequires knowing JSX rulesPure JavaScript, no new syntax
Tooling supportExcellent (linters, formatters, TS)Works but no IDE-level JSX tooling
Build step requiredYesNo (but rarely done in practice)

What Interviewers Actually Check

  • Whether you know JSX compiles to React.createElement and what that means for the rules
  • Whether you can explain why component names must be uppercase
  • Whether you can explain three JSX attribute differences from HTML and why they exist
  • Whether you know why if statements cannot go inside curly braces
  • Whether you know the new JSX transform and why it removes the React import requirement

Follow-Up Questions

  1. Can you write React components without JSX at all? What are the downsides?
  2. How does TypeScript type-check JSX? What is JSX.Element vs React.ReactNode vs React.ReactElement?
  3. What is the pragma comment /** @jsx ... */ and when would you use it?
  4. What does the React.StrictMode wrapper do that is specific to development mode?
  5. How does JSX handle whitespace between elements compared to HTML?

Common Candidate Mistakes

  • Saying JSX is HTML, not knowing it is a JavaScript expression that compiles to function calls
  • Not knowing that the build step is required and wondering why JSX does not work natively in the browser
  • Writing class= instead of className= and not knowing why it must be different
  • Trying to write { if (show) { return <div /> } } inside JSX and not understanding why it fails
  • Not knowing that falsy values like 0 render as text in JSX ({count && ...} where count is 0 renders "0")

Interview Readiness Checklist

Before you leave this question, make sure you can answer:

  • Can you explain what JSX compiles to and show a before/after example?
  • Can you list three JSX attribute differences from HTML and explain why each exists?
  • Can you explain why if/else statements do not work inside curly braces and what to use instead?
  • Can you write a JSX expression with conditional rendering, event handlers, and a mapped list?
  • Can you explain why the new JSX transform removes the need to import React in every file?

Summary

JSX is syntactic sugar that transforms human-readable markup into React.createElement function calls. Each JSX element compiles to React.createElement(type, props, ...children). This compilation happens at build time via Babel or the React compiler; browsers never execute JSX directly.

The compilation to function calls is the root cause of several JSX rules. Component names must be uppercase so the JSX transform uses a variable reference rather than a string. Attribute names use camelCase and differ from HTML attributes (className, htmlFor) because JSX is JavaScript and cannot use reserved keywords as property names. Only expressions are valid inside curly braces because the curly-brace content becomes a function argument.

JSX exists as a developer experience choice: it makes the component output structure visible in the source code, with logic and markup collocated rather than separated into templates and script files. The tradeoff is a required build step, but every React toolchain (Create React App, Vite, Next.js) configures this automatically.

Frequently Asked Questions

Is JSX valid JavaScript?

No. JSX is a syntax extension to JavaScript. Browsers cannot execute JSX directly. Babel or the React compiler transforms JSX into React.createElement calls before the code runs in the browser.

Advertisement


Stay Updated

Get the latest frontend challenges, interview questions and tutorials delivered to your inbox.

Advertisement