Skip to content

React Tutorial JSX and Components

JSX Syntax Rules and Expressions

Lesson 20 of 156 2 min read By Deepak Paswan Updated Oct 10, 2026

Runnable lesson · press Try it on the examples to edit and run them here.

JSX has only a few rules. Once you know them, most JSX errors become easy to read. Each rule below has a reason.

Rule 1: return one root element

A component can return only one thing. Two sibling elements at the top level are an error:

App.jsx
JSX
// Error: adjacent JSX elements must be wrapped
function App() {
  return (
    <h1>Title</h1>
    <p>Text</p>
  );
}

Under the hood, JSX turns into a function call, and a function returns one value. Wrap the elements in a parent:

App.jsx
JSX
function App() {
  return (
    <div>
      <h1>Title</h1>
      <p>Text</p>
    </div>
  );
}

If you do not want an extra <div> in the page, use a Fragment: <> ... </>. See Fragments.

Rule 2: close every tag

HTML lets you leave out some closing tags. JSX does not. Elements with no children are self-closing:

App.jsx
JSX
function App() {
  return (
    <form>
      <label>
        Name <input aria-label="Name" />
      </label>
      <br />
      <img alt="A one pixel dot" width="8" height="8" src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=" />
    </form>
  );
}

<input />, <br /> and <img ... /> all end with />.

Rule 3: use camelCase attribute names

JSX attributes become JavaScript object keys, so they follow JavaScript naming: className, htmlFor, onClick, tabIndex, maxLength. The exceptions are data-* and aria-*, which keep their hyphens.

Rule 4: use parentheses for multi-line JSX

A return followed by a new line returns undefined because of JavaScript’s automatic semicolon insertion. Put the opening tag on the same line as return, or wrap the JSX in parentheses:

App.jsx
JSX
function App() {
  return (
    <div>
      <p>Safe</p>
    </div>
  );
}

Rule 5: curly braces open a JavaScript window

Inside JSX, { ... } lets you write a JavaScript expression. An expression is anything that produces a value:

App.jsx
JSX
function App() {
  const name = "Ada";
  const a = 2;
  const b = 3;

  return (
    <div>
      <p>Hello, {name}!</p>
      <p>{a} + {b} = {a + b}</p>
      <p>{name.toUpperCase()}</p>
      <p>{a > b ? "a is bigger" : "b is bigger"}</p>
    </div>
  );
}

Everything inside the braces is evaluated, and the result is shown. You can put variables, arithmetic, function calls and ternaries there. You cannot put statements such as if, for or const. Embedding Expressions goes deeper.

Rule 6: comments need braces

An HTML comment (<!-- -->) does not work in JSX. Use a JavaScript comment inside braces:

App.jsx
JSX
function App() {
  return (
    <div>
      {/* This comment is not shown */}
      <p>Visible</p>
    </div>
  );
}

Whitespace

JSX removes whitespace at the start and end of lines and joins text lines with a single space. If you need an exact space between two elements on separate lines, write {" "}:

App.jsx
JSX
function App() {
  return (
    <p>
      <b>Hello</b>{" "}
      <i>World</i>
    </p>
  );
}

Key points

  • Return one root element, close every tag, use camelCase attributes.
  • { } evaluates a JavaScript expression; statements are not allowed.
  • Comments in JSX go in {/* */}.