HTML to JSX Converter
Processed Client SidePaste HTML and get valid JSX — class becomes className, inline styles become objects, and every attribute is renamed the way React expects. Runs entirely in your browser.
Bookmark this tool now — skip the search next time you need it.
About HTML to JSX Converter
This tool runs entirely in your browser. Whatever you paste is processed on your own device and is never uploaded, logged, or sent to any server.
Pasting HTML straight into a React component does not work, and the reasons are scattered: `class` is a reserved word, `for` is a statement, `onclick` holds a string where JSX wants a function, and `style` is a CSS declaration list where React wants an object. This converter fixes all of them at once. It parses the markup into a tree first — rather than running find-and-replace over the text — which is what lets it know that the `<` in `if (a < b)` inside a script is not a tag, that the space between two inline elements is rendered and must survive being put on its own line, and that a `<li>` you never closed still ends where the browser ends it. Everything runs in your browser, so an unreleased template is never uploaded.
Key features
- Every attribute renamed the way React expects: class to className, for to htmlFor, tabindex to tabIndex, and the whole camelCase set down to onCanPlayThrough
- data-* and aria-* attributes pass through untouched, and so do custom ones like ng-model or hx-get — only the hyphenated SVG presentation attributes are camelCased, because those are the ones React maps onto DOM properties
- Inline `style` becomes a real style object, with vendor prefixes capitalised correctly (WebkitTransform, but msTransform) and custom properties kept as quoted keys
- Inline handlers become functions: onclick="save()" comes out as onClick={() => save()}, and a handler that leans on `this` or `event` is flagged rather than quietly converted
- Entities are decoded, and the invisible ones are written as escapes — a becomes {'\u00A0'} instead of a character you cannot tell from a space in a diff
- JSX syntax characters in your text are escaped, so a stray {, }, < or > in the copy does not turn into a parse error
- The awkward elements are handled individually: <pre> and <style> keep their content verbatim in a template literal, <textarea> gets defaultValue instead of children, and comments become {/* … */}
- Output as bare JSX, a function component, or an arrow component, with a name you choose and 2-space, 4-space or tab indentation
- Rendered whitespace is preserved across line breaks with an explicit {' '}, which is the difference between "Hello world" and "Helloworld" once the markup is formatted
- Warnings for what React will complain about later — an unclosed tag, a <tr> with no <tbody>, an <option selected>, a prop that had to be dropped
- Converts as you type, entirely in your browser — nothing you paste is uploaded
How to use it
- Paste your HTML into the left pane, replacing the sample.
- Choose what you want out: JSX only if you are pasting into an existing component, or a function or arrow component if you want a whole file.
- Name the component if you picked one of the component modes — the name is capitalised for you, because JSX reads a lower-case tag as an HTML element.
- Pick your indentation, and decide whether form fields should use value or defaultValue.
- Read the badges under the output: they count what was converted and flag anything React will object to.
- Copy the JSX or download it as a .jsx file.
Tips & common mistakes
- Leave "value → defaultValue" on unless you are about to wire the field up. React treats an input with a `value` and no `onChange` as read-only and warns in the console; `defaultValue` is what makes it an ordinary uncontrolled field that people can type in.
- The {' '} expressions in the output are load-bearing, not clutter. JSX deletes any whitespace run that contains a newline at the start or end of a line, so a space between two inline elements has to be written explicitly once the line is broken.
- A <script> body cannot become JSX children, so it is moved to dangerouslySetInnerHTML — and React will not execute it there. Move the code into your component instead; the converted markup is a placeholder, not a working script tag.
- Everything the converter cannot express is reported rather than silently dropped. `!important` in an inline style is the common one: React sets styles through the element’s style property, which rejects a declaration carrying a priority, so the flag comes off and the warning tells you where.
- Framework attributes survive if they are valid JSX names and are dropped if they are not. `v-if` and `ng-model` come through as written; `@click`, `:href` and `(ngSubmit)` cannot be JSX props at all, and get a warning instead of output that will not parse.
- Converting an SVG icon works well and is a common reason to use this. The hyphenated presentation attributes become camelCase, and the elements whose spelling matters — linearGradient, clipPath, feGaussianBlur — get their capitals back, which HTML parsing had lower-cased.
- The output is formatted, not just translated: attributes break one per line past 80 columns and short elements stay on one line. If you run Prettier on your project, expect it to agree with most of this and reflow the rest — the conversion is what matters, the layout is a starting point.
- This converts markup, not behaviour. An inline handler becomes an arrow function calling the same code, but that code still has to exist in scope, and `this` inside it no longer means the element it was written on.