Migrating from HTML to JSX: Common Pitfalls and How to Avoid Them
ReactJSXFrontend

Migrating from HTML to JSX: Common Pitfalls and How to Avoid Them

JSX Is Not HTML

This distinction matters more than it might seem. JSX is a syntax extension for JavaScript that looks like HTML but compiles to JavaScript function calls. <div className="box">Hello</div> becomes React.createElement("div", { className: "box" }, "Hello"). Understanding this helps explain why JSX rules exist — they are constraints of JavaScript, not of HTML.

The good news: most HTML converts to JSX with only minor changes. The bad news: those minor changes are inconsistent enough that they trip up developers moving between plain HTML templates and React components regularly.

The Full List of Differences

Attribute Name Changes

JSX attributes use camelCase JavaScript property names, not HTML attribute names. The most important:

  • classclassName (reserved word in JavaScript)
  • forhtmlFor (reserved word in JavaScript)
  • tabindextabIndex
  • readonlyreadOnly
  • maxlengthmaxLength
  • autocompleteautoComplete
  • contenteditablecontentEditable
  • crossorigincrossOrigin

Self-Closing Tags

In HTML5, void elements (<br>, <img>, <input>, <hr>, <meta>, <link>) do not need closing tags. In JSX, every element must be closed, either with a closing tag or the self-closing shorthand:

// HTML
<br>
<img src="photo.jpg" alt="Photo">
<input type="text">

// JSX
<br />
<img src="photo.jpg" alt="Photo" />
<input type="text" />

Inline Styles

In HTML, style is a string: style="color: red; font-size: 14px". In JSX, style is an object with camelCase property names and string values (or unitless numbers for pixel values):

// HTML
<div style="color: red; font-size: 14px; background-color: #f0f0f0">

// JSX
<div style={{ color: 'red', fontSize: '14px', backgroundColor: '#f0f0f0' }}>

The double curly braces are not magic — the outer {} is JSX's "enter JavaScript expression" syntax, and the inner {} is a JavaScript object literal.

Event Handlers

HTML events use lowercase attribute names. JSX uses camelCase:

  • onclickonClick
  • onchangeonChange
  • onsubmitonSubmit
  • onkeydownonKeyDown
  • onmouseenteronMouseEnter

In HTML, event handlers are strings: onclick="handleClick()". In JSX, they are function references: onClick={handleClick}. Do not call the function — pass a reference. onClick={handleClick()} calls the function immediately during render, which is almost never what you want.

JSX Comments

HTML comments (<!-- comment -->) do not work in JSX. Use JavaScript comments inside an expression block:

{/* This is a JSX comment */}
<div>{/* Another comment */}</div>

Single Root Element

JSX expressions must have exactly one root element. If you need to return multiple elements without a wrapper div, use a Fragment:

// This fails — two root elements
return (
  <h1>Title</h1>
  <p>Paragraph</p>
);

// Use Fragment — renders no extra DOM element
return (
  <>
    <h1>Title</h1>
    <p>Paragraph</p>
  </>
);

Boolean Attributes

In HTML, the presence of an attribute implies true: <input disabled>. In JSX, boolean attributes must be explicitly set:

<input disabled={true} />
// Or shorthand: JSX treats a bare attribute as true
<input disabled />

To set an attribute to false, pass the value explicitly: <input disabled={false} /> — which is the same as omitting the attribute entirely.

The dangerouslySetInnerHTML Warning

HTML's innerHTML equivalent in JSX is dangerouslySetInnerHTML — the name is intentional. Inserting raw HTML from user input without sanitization is a major XSS vulnerability. Only use this with content you fully control or that has been sanitized server-side:

<div dangerouslySetInnerHTML={{ __html: sanitizedHtmlString }} />

Automate the Conversion

Converting large amounts of HTML to JSX by hand is error-prone and tedious. Use PureFormatter's HTML to JSX converter to handle all attribute renaming, self-closing tag corrections, and style object conversions automatically. It handles edge cases like inline SVG, data attributes, and aria attributes correctly.

Fredy
Written by
Fredy
Senior Developer & Technical Writer

Fredy is a full-stack developer with 8+ years of experience building web applications. He writes about developer tools, best practices, and the craft of clean code.