Hardware FixRecommendedDevice not working? Your driver may be the problemCheck updates for common hardware issues.Fix DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan Now×
Skip to content
frontend

How to Convert HTML Code to React Components (HTML-to-JSX Guide)

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Direct answer: converting HTML to a React component means moving the markup into a JavaScript function that returns JSX, then fixing JSX’s stricter syntax. Add one root element (or a Fragment), close every tag, rename attributes such as class to className, use camelCase DOM/SVG properties, and put dynamic values in braces. After the markup compiles, split repeated UI into child components and pass changing data through props.

What you are converting: HTML into JSX

JSX is a JavaScript syntax extension that lets you write HTML-like markup inside a JavaScript file. A React component is commonly a JavaScript function that returns that markup. JSX looks familiar, but it is stricter than browser HTML: it must have a single root, every element must be closed, and attribute names follow JavaScript and DOM property conventions.

Step 1: Put the HTML in a function component

Start with a named function and return the copied structure. This example is valid HTML:

<div class="card">
  <img src="/avatar.png">
  <h2>Profile</h2>
</div>

The equivalent component is:

export default function ProfileCard() {
  return (
    <div className="card">
      <img src="/avatar.png" alt="Profile" />
      <h2>Profile</h2>
    </div>
  );
}

Place the file where your project’s JSX transform expects components (for example, a .jsx file). Your configured Babel, framework, or build tool then transforms the JSX. Babel supports an automatic runtime (added in version 7.9.0) that emits imports for jsx/jsxs, and a classic runtime that emits React.createElement calls.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Step 2: Fix JSX structure and tag syntax

Use one root element

Adjacent top-level elements are invalid. Wrap them in a semantic element or a Fragment:

return (
  <>
    <header>Site title</header>
    <main>Content</main>
  </>
);

A Fragment adds no DOM node. Use a real wrapper when it improves semantics, styling, or layout.

Close every element

HTML permits some omitted end tags; JSX does not. Void elements must self-close: <img />, <input />, <br />, <hr />, and <meta />. Add useful alt text to images while converting.

Preserve nesting

Correct invalid browser-tolerated nesting before JSX compilation. A compiler will report the location of a malformed tree rather than silently repairing it as a browser might.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Step 3: Rename HTML attributes to JSX properties

JSX uses DOM property names instead of every HTML spelling. The high-value replacements are:

HTML JSX Why it matters
class className class is reserved in JavaScript; React uses the corresponding DOM property.
for htmlFor Associates a label with its control.
stroke-width strokeWidth Many DOM and SVG properties use camelCase.
tabindex tabIndex Uses the DOM property spelling.
aria-label, data-id unchanged aria-* and data-* attributes retain hyphens.

Do not blindly camelCase every attribute: accessibility and custom data attributes are the important exception. Check compiler diagnostics for less common properties.

Step 4: Move values and logic into braces

Quoted JSX attributes are static strings. JavaScript expressions go inside curly braces:

export default function ProductCard({ product, featured }) {
  return (
    <article className={featured ? "card card--featured" : "card"}>
      <img src={product.imageUrl} alt={product.name} />
      <h2>{product.name}</h2>
      <p>{product.price}</p>
    </article>
  );
}

Expressions can read props, call formatting functions, use conditional operators, or render lists. Statements such as if and for belong outside the returned markup (or can be expressed with helper functions and array methods).

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Convert repeated HTML to a list

const links = [
  { id: 1, label: "Docs", href: "/docs" },
  { id: 2, label: "Pricing", href: "/pricing" }
];

export default function Navigation() {
  return (
    <nav aria-label="Primary">
      <ul>
        {links.map((link) => (
          <li key={link.id}>
            <a href={link.href}>{link.label}</a>
          </li>
        ))}
      </ul>
    </nav>
  );
}

Give each repeated sibling a stable key from the data. Avoid using the array index when items can be inserted, removed, or reordered.

Step 5: Turn sections into reusable components

A pasted template is only the starting point. Extract a section when it has a clear responsibility, repeats, or needs independent data. Pass changing content through props:

function Alert({ tone = "info", children }) {
  return <div className={`alert alert--${tone}`}>{children}</div>;
}

export default function AccountPage() {
  return (
    <main>
      <h1>Account</h1>
      <Alert tone="success">Your profile is saved.</Alert>
    </main>
  );
}

Use children for nested content and named props for data or behavior. Keep a component’s prop interface small; this makes later refactoring easier than copying another large HTML block.

Step 6: Convert forms and event handlers

HTML event attributes such as onclick are not JSX event handlers. Use camelCase names and pass a function, not a string:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import { useState } from "react";

export default function SignupForm() {
  const [email, setEmail] = useState("");

  function handleSubmit(event) {
    event.preventDefault();
    // Send email to your application here.
  }

  return (
    <form onSubmit={handleSubmit}>
      <label htmlFor="email">Email</label>
      <input
        id="email"
        name="email"
        type="email"
        value={email}
        onChange={(event) => setEmail(event.target.value)}
        required
      />
      <button type="submit">Join</button>
    </form>
  );
}

For a controlled input, keep the value in state and update it in onChange. Preserve the original form’s labels, keyboard behavior, validation attributes, and button types.

Step 7: Keep CSS, but change the class attribute

Existing stylesheet classes continue to work. Import the stylesheet as your project requires and reference classes with className:

import "./card.css";

export default function Card() {
  return <section className="card card--compact">Content</section>;
}

Use an object-valued style prop only when styles depend on runtime values. Property names become camelCase and numeric values may receive pixel units:

<div style={{ backgroundColor: themeColor, marginTop: 12 }} />

Do not paste a CSS declaration string into style; JSX expects an object.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Step 8: Handle SVG and accessibility carefully

Inline SVG usually needs the same camelCase treatment as DOM properties: stroke-width becomes strokeWidth, and similar names follow the JSX property spelling. Keep aria-label, role, and data-* attributes intact. Preserve heading order, label/control relationships, keyboard focus, alternative text, and meaningful landmark elements while converting; a visually identical component can still be less accessible if these details are lost.

Rendering existing raw HTML: use an escape hatch cautiously

If the source arrives as a string from a CMS, React provides dangerouslySetInnerHTML:

export default function ArticleBody({ html }) {
  return <div dangerouslySetInnerHTML={{ __html: html }} />;
}

Passing untrusted content this way is a security hole because it can allow injected markup or scripts. Prefer converting known template markup into JSX, or sanitize content with a security-reviewed pipeline before rendering. Never treat user-submitted HTML as safe merely because it came from a form or API.

Manual conversion versus an HTML-to-JSX converter

Concern Manual JSX conversion Converter output
Syntax renaming Slower, but you see every decision. Fast for mechanical changes such as className and self-closing tags.
Malformed HTML You can repair structure deliberately. Results depend on how the tool parses invalid markup; review is required.
SVG attributes You can verify each property. May rename common properties but still needs inspection.
Accessibility attributes Easy to preserve intentionally. Check that aria-* and data-* spelling was retained.
Components and props Supports meaningful boundaries and data flow. Usually produces one mechanical block, not a maintainable component design.
Security Lets you avoid raw HTML insertion. Does not make untrusted HTML safe.

A converter can save typing, but it cannot decide component boundaries, event behavior, data flow, accessibility, or trust boundaries. Treat its output as a first draft and compile it immediately.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Compile, test, and refactor in that order

  1. Run the project’s normal development or build command so the configured JSX transform reports exact errors.
  2. Fix the first syntax error, especially missing roots, unclosed tags, or invalid property names; later errors may be consequences.
  3. Render the component and compare desktop, mobile, keyboard, and screen-reader behavior with the original page.
  4. Test links, forms, focus states, conditional branches, empty data, long text, and failed images.
  5. Extract repeated sections only after the converted markup renders correctly; then add props and stable list keys.

Troubleshooting common conversion errors

“Adjacent JSX elements must be wrapped”

There is more than one top-level sibling. Wrap the return value in a semantic element or <>...</>.

“Expected corresponding closing tag”

An HTML end tag is missing or nested incorrectly. Close every element and self-close void elements.

“Property ‘class’ does not exist”

Change class to className. Change label for to htmlFor.

An SVG renders incorrectly

Check camelCase SVG properties such as strokeWidth, and inspect the browser console for the exact unknown-property warning.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Styles disappeared

Confirm the CSS file is imported, the selector matches the new className, and any CSS-module import uses the project’s generated class name rather than a global string.

Events do nothing

Use onClick, onSubmit, and similar camelCase handlers with function values. Do not use HTML strings such as onclick="...".

List warnings mention keys

Add a stable, unique key to the element returned by map; do not generate a new random key on every render.

Content is unsafe or unexpectedly escaped

Normal JSX escapes text safely. If you used dangerouslySetInnerHTML, stop and sanitize untrusted HTML before rendering, or model the content as components and data.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your goal is a clean image or PDF of the converted page rather than a local browser capture, ScreenshotNeo provides a website screenshot API and MCP server. After your React page is deployed, one GET request is enough:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo documentation for request options. The same endpoint works from Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

And Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
  • Cookie and consent banners, newsletter popups, and chat widgets are removed before the shot; each cleanup step can be disabled.
  • Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed. Response headers identify the page verdict and whether it was billed.
  • An MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.
  • The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Every feature is on every plan.

Create a free ScreenshotNeo account to start.

FAQ

Can I paste a complete HTML document into a component?

Use the document’s body content as component markup. A React component should not return document-level elements such as html, head, and body as a page shell unless your framework explicitly supports that pattern.

Do React components have to be written in TypeScript?

No. JSX works in JavaScript files; TypeScript with TSX is an optional type-checking layer.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Should every HTML element become its own component?

No. Extract units with a meaningful responsibility or reuse. Over-splitting makes props and navigation harder to follow.

Why does JSX reject a style string?

The JSX style prop expects a JavaScript object whose property names use camelCase, not a semicolon-separated CSS string.

Frequently Asked Questions

Can I paste a complete HTML document into a component?

Use the document’s body content as component markup. A React component should not return document-level elements such as html, head, and body as a page shell unless your framework explicitly supports that pattern.

Do React components have to be written in TypeScript?

No. JSX works in JavaScript files; TypeScript with TSX is optional.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Should every HTML element become its own component?

No. Extract units with a meaningful responsibility or reuse.

Why does JSX reject a style string?

The style prop expects a JavaScript object with camelCase property names.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.