דלגו לתוכן
academeez

The Rules of JSX

תוכן זה אינו זמין עדיין בשפה שלך.

If you are already familiar with HTML, learning JSX is a short step—both look very similar. In this lesson we focus on what makes JSX different: each section explains one rule, with an example that shows how JSX diverges from HTML. Then you get an online IDE with code that breaks that rule, and you fix it by applying what you just learned.

We learn by writing code—that is the best way to learn.

A React component must return a single root element. You cannot return two sibling tags at the top level of return—React will report that adjacent JSX elements must be wrapped.

In HTML you can place many elements next to each other inside <body>. In JSX, the component’s return is one expression, so multiple siblings need a wrapper.

The example below is broken. When you run it, you will see an error like this:

The important part is the message: Adjacent JSX elements must be wrapped in an enclosing tag. Fix the component below by wrapping the markup in a <div>:

Sometimes you need a wrapper to satisfy the single-root rule, but you do not want an extra node in the DOM—for example when a parent already provides layout and an added <div> would break styling or semantics.

For that case React has a Fragment: <>...</>. It groups elements without rendering an extra tag in the browser.

In the editor above, replace your <div> wrapper with a Fragment.

HTML is more forgiving when you leave tags open. In JSX you must either close every tag (<li>...</li>) or use a self-closing tag (<img />, <br />).

Here is code that would work in HTML but breaks in JSX—an <img> that is not self-closing, and list items that are not closed. When you run it, you will see an error like this:

Notice how clear the exception is—it points at the problem and tells you what JSX expected: Expected corresponding JSX closing tag for <li>. Reading and understanding error messages is an important skill in programming.

Fix both issues in the editor below:

React usually uses DOM property names rather than HTML attribute names. That is why some attributes look different in JSX—for example, class and for on HTML become className and htmlFor (which are also JavaScript reserved words, but the pattern is broader than that).

For example, in HTML you place class on a tag:

<img class="some-css-class" ... />

When the browser creates an HTMLImageElement from that tag, the class attribute becomes a property called className on the DOM element.

React generally follows DOM property names rather than HTML attribute names. To follow JavaScript conventions, those property names are mostly camelCased and do not use reserved words. Since the DOM property is element.className, JSX uses className:

<img className="some-css-class" ... />

In HTML, for is an attribute on a <label> that connects the label to an <input>:

<form>
<label for="username">Username</label>
<input type="text" name="username" id="username" />
</form>

For labels, the DOM property is htmlFor, so JSX uses htmlFor:

<form>
<label htmlFor="username">Username</label>
<input type="text" name="username" id="username" />
</form>

Unlike the syntax errors above, using class or for in JSX may not break the preview—the app can still render. React logs warnings in the console instead:

This example shows why it is important to read console errors and warnings and understand them—not only hard errors. A warning can still point to a serious bug. On a plain DOM element React may still output class or for in the HTML despite the warning—but in CssClass.js the styled box only reads className, so the yellow background does not appear until you fix it.

The editor below shows the console panel so you can see those warnings. Fix the mistakes in the two component files and watch the warning logs disappear:

  • CssClass.js — uses class on <StyledBox>; change it to className and watch the yellow background appear
  • Form.js — uses for on a <label>; change it to htmlFor

In HTML, many attribute names are lowercase or kebab-case. In JSX, most of them become camelCase—matching JavaScript conventions for variables and object properties, and the same names you would use on the matching DOM property.

Here are a few valid HTML attributes and how they look in JSX:

tabindex — controls tab order on focusable elements:

HTML:

<button tabindex="0">Click me</button>

JSX:

<button tabIndex="0">Click me</button>

stroke-width — common on SVG elements:

HTML:

<circle stroke-width="2" />

JSX:

<circle strokeWidth="2" />

React preserves aria-* and data-* exactly as defined by the HTML and accessibility specifications—you do not camelCase them.

aria-label — describes an element for assistive technology:

HTML:

<button aria-label="Close">×</button>

JSX:

<button aria-label="Close">×</button>

For the majority of other attributes, camelCase is the rule.

Notice how React warns you in the console when attributes are not camelCase. Fix the mistakes in the editor below and get no warnings in the console:

  • LoginForm.js — a login form with username, password, and submit button; fix tabindex on each control
  • SvgCircle.js — an SVG circle with several kebab-case attributes; fix them to camelCase

The last rule we will cover—and only briefly, because we have a full lesson on it—is how easy it is to insert JavaScript expressions directly into JSX.

With curly braces {} you can insert a JavaScript expression directly into your markup. You can use them in tag attributes, for example:

function Form() {
const username = 'academeez';
return (
<form>
<input type="text" value={username} />
</form>
)
}

Or you can embed an expression between element tags. For example:

function Avatar() {
const firstName = 'academeez';
const lastName = 'Free coding lessons';
return (
<p>
Your first name is: {firstName} and last name is: {lastName}
</p>
)
}

You cannot use a JavaScript expression as a tag name. Dynamic tags are possible, but in other ways—we will not cover that in this lesson. Doing this is not correct:

function DynamicTag() {
const tagType = 'p';
return (
<{tagType}>this code is wrong</{tagType}>
)
}

In this lesson we learned the main rules of JSX by fixing broken code in the online IDE. JSX looks like HTML, but it follows stricter rules because it lives inside JavaScript.

  • Return a single root element — wrap siblings in a <div> or a Fragment (<>...</>).
  • Close every tag — use self-closing tags where needed (<img />, <li>...</li>).
  • Use DOM property names — mostly camelCased and avoiding JavaScript reserved words; for example className and htmlFor instead of HTML class and for.
  • Use camelCase for most attributes — for example tabIndex and strokeWidth; aria-* and data-* stay kebab-case.
  • Insert JavaScript with {} — in attribute values or between tags (we will go deeper in future lesson).

When something is wrong, read the error messages and console warnings—they often tell you exactly what to fix.

Next up: a separate HTML to JSX transformer page powered by transform (transform.tools)—paste your HTML and it will automatically convert it to JSX using the rules from this lesson.