Chapter 4 of 20 · React for Beginners — Complete Free Tutorial

JSX Explained

Every example in the React for Beginners series so far has mixed HTML-looking tags into JavaScript. That is JSX, and it is the first thing that surprises newcomers: it is not HTML, it is not a string, and it does not run in the browser untouched. This chapter explains what JSX really is, how to embed JavaScript inside it, and the exact ways it differs from the markup you know.

JSX is a syntax extension

JSX is sugar that a build step compiles into plain JavaScript function calls. Vite does this compilation for you, so you never configure it — but knowing what happens demystifies error messages. Your component body:

const element = (
  <button className="primary" onClick={handleSave}>
    Save
  </button>
);

is transformed into roughly this (names shortened for clarity):

const element = jsx('button', {
  className: 'primary',
  onClick: handleSave,
  children: 'Save',
});

Expected output: no visual output — but it explains two facts. JSX produces a plain JavaScript object describing UI (a "React element"), and the browser never parses your JSX as markup. The JavaScript stays raw; only the tag-shaped parts are transformed.

Embedding expressions with curly braces

Anything inside { } is evaluated as JavaScript and inserted as a value. Both must be real expressions — statements like if or let do not belong inside braces.

const user = { name: 'Ada', admin: true };
const items = ['JSX', 'props', 'state'];

function Profile() {
  return (
    <section>
      <h2>{user.name}</h2>
      <p>You have {items.length} chapters queued.</p>
      <ul>{items.map((item) => <li key={item}>{item}</li>)}</ul>
      {user.admin && <span className="badge">Admin</span>}
    </section>
  );
}

Expected output:

Ada
You have 3 chapters queued.
- JSX
- props
- state
Admin          (because user.admin is true)

Notice && for a simple condition and key on list items — both get dedicated chapters later.

HTML vs JSX: the differences that bite

JSX follows HTML's shape but JavaScript's rules, and several familiar attributes were renamed to avoid clashing with reserved words:

HTMLJSXReason
class="card"className="card"class is a reserved JavaScript word
for="email"htmlFor="email"Same — for is a loop keyword
style="color: red"style={{ color: 'red' }}Styles are an object, property names camelCased
tabindex="1"tabIndex={1}HTML attributes become camelCase
<img>, <br><img />, <br />Every tag must be closed or self-closed
onclick="..."onClick={handler}Handlers are functions, not strings

Tags, fragments and children

Adjacent elements need a single parent. You can wrap them in a plain div, but an empty fragment <>…</> adds nothing to the page — useful when a wrapper would break your CSS layout:

function Row({ label, value }) {
  return (
    <>
      <dt>{label}</dt>
      <dd>{value}</dd>
    </>
  );
}

Expected output: a definition-list row rendered without any extra wrapper element between dl, dt and dd.

Why JSX beats template strings

You could build HTML with template literals and innerHTML, but JSX wins on three fronts. It is structured, so malformed nesting is a compile error instead of a runtime surprise. It is safe, because React escapes values by default — text inserted through braces can never inject markup. And it is composable: you embed components (<Greeting />) the same way you embed tags, which templates cannot express.

Reading JSX errors

Most beginner JSX errors name a line and a symbol: "Unterminated string", "Expected corresponding JSX closing tag", or "Identifier has not been declared". When a build error points at a file, check three things in order — balanced tags, matched braces, and imports for every component used.

Common mistakes

  • Using class instead of className — React ignores class entirely, so your styles silently vanish.
  • Writing statements inside braces — { if (x) {…} } is invalid; use an expression such as {x && …} or a ternary.
  • Forgetting to close tags — <img …> must be <img … />; the compiler will stop you, but the error line can point at the next line.
  • Treating style as a string — style="color:red" is a string and React expects an object with camelCase keys.
  • Escaping text unnecessarily — React escapes values inserted through braces automatically; do not hand-encode HTML.

Practice checklist

  1. Rewrite a plain HTML snippet from memory in JSX, renaming every changed attribute.
  2. Render an object's three properties using curly-brace expressions.
  3. Convert an if statement inside markup into && and then into a ternary.
  4. Introduce a deliberate mismatched closing tag and read the compiler error until it makes sense.
  5. Render a list with map and confirm each item carries a key prop.

JSX is the language; now it needs inputs — continue with Props: Passing Data Between Components.

Quiz: JSX Explained

5 questions · 70% to pass

Frequently Asked Questions

React is a JavaScript library for building user interfaces from reusable components. It manages how your UI updates when data changes, so you describe what the screen should look like and React performs the efficient DOM updates. It is one of the most in-demand frontend skills and powers products from Netflix to Instagram, which makes it an excellent next step after core JavaScript.

You should be comfortable with functions, arrays and objects (map, filter, spread), destructuring, modules and basic async/await. React itself is written in plain JavaScript — JSX is a syntax layer on top. If any of those feel shaky, revisit the JavaScript fundamentals first and this series will go much faster.

React is a library focused only on the UI layer — you choose your own router, data layer and tooling. Angular is a full framework that ships routing, forms, HTTP client and testing conventions as one opinionated package. React's flexibility and huge ecosystem make it the common choice for teams that want to compose their own stack.

A component is a reusable function that returns UI. It receives input through props, keeps private data in state, and can render other components. Pages are composed by nesting small components (navbar, card list, footer) instead of one giant file, which keeps code testable and easy to change.

JSX is a syntax extension that looks like HTML but compiles to React's create() calls — it is a description of UI, not markup the browser parses. Small differences matter: class becomes className, style takes an object, and you embed JavaScript expressions inside curly braces. Once compiled, React turns that description into real DOM nodes.

Props are inputs passed from a parent — they are read-only inside the child, like function arguments. State is private, mutable data owned by a component; updating it triggers a re-render. The rule of thumb: values that come from outside the component are props; values that change over the component's lifetime are state.

Rendering means calling your component function to produce a description of the UI for the current state and props. It does not always mean DOM work — React compares the new description with the previous one (reconciliation) and applies only the differences to the real DOM. This is why updating state 100 times does not mean 100 full page rebuilds.

An effect runs after the component has committed to the screen — after render, not during it. You list dependencies in an array, and React re-runs the effect only when one of them changes. If the effect returns a cleanup function, React runs it before the next re-run and on unmount, which is where you cancel timers, abort fetches and remove listeners.

Use Vite. Create React App is effectively in maintenance mode, while Vite starts instantly (native ES modules) and builds fast, and it is the default choice for new React projects. This series uses Vite for every example — you only need Node.js installed to follow along.

React apps compile to static files (HTML, CSS and JavaScript), so any static host works: Netlify, Vercel, GitHub Pages or Cloudflare Pages. Run the production build, upload the dist folder, and configure a single-page-application fallback so unknown paths load index.html — routing chapters explain why that fallback is required.