Help

JSX to JS Converter: Compile React JSX to Plain JavaScript

A JSX to JS converter turns the tag syntax of React components into the plain JavaScript a browser can run. This one uses Babel, so the output matches what a Babel build step would write. You choose between the classic React.createElement calls and the automatic jsx() runtime, and copy the result. It is made for one component or snippet at a time. The code is compiled in your browser, never uploaded and never run.


How to convert JSX to JS online

  1. Paste your code into JSX code. The box reads Paste JSX here… until you do. The limit is 1,000,000 characters.
  2. Wait a moment. The tool compiles as you type or paste, about a third of a second after the last change, so there is no button to press. The first time, Babel downloads once, which takes a little longer.
  3. Read the result under the heading JavaScript. It is shown as read-only highlighted code.
  4. Select Copy to clipboard. The button changes to Copied.
  5. To change how the JSX is compiled, use the gear button beside it (JSX runtime settings). It opens the JSX runtime group with two choices, Classic and Automatic. Change it and the code compiles again.

If the text is not valid JSX you see This is not valid JSX: syntax error at line N, column M. with the offending line and a caret under the spot, and no output until it is fixed. If the code has no JSX in it at all, the tool shows it back as plain JavaScript and says No JSX was found in this code, so it came back as plain JavaScript.

A worked example: one component, both runtimes

This is the input, a small component with a fragment, a prop, an event handler and a comment:

import { useState } from 'react'; export function Counter({ label }) { // one click, one update const [n, setN] = useState(0); return ( <> <h2 className="title">{label}</h2> <button onClick={() => setN(n + 1)}>Clicked {n} times</button> </> ); }

With Classic, the default, the converter writes this:

import { useState } from 'react'; export function Counter({ label }) { // one click, one update const [n, setN] = useState(0); return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("h2", { className: "title" }, label), /*#__PURE__*/React.createElement("button", { onClick: () => setN(n + 1) }, "Clicked ", n, " times")); }

With Automatic, it writes this:

import { useState } from 'react'; import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; export function Counter({ label }) { // one click, one update const [n, setN] = useState(0); return /*#__PURE__*/_jsxs(_Fragment, { children: [/*#__PURE__*/_jsx("h2", { className: "title", children: label }), /*#__PURE__*/_jsxs("button", { onClick: () => setN(n + 1), children: ["Clicked ", n, " times"] })] }); }

Both results are the same component. In the classic output every tag is a React.createElement call, and the fragment is React.Fragment. Nothing imports React, so the file needs import React from 'react' or React already in scope. In the automatic output the converter has added the react/jsx-runtime import itself. The children move into the props object as children, an element with one child uses _jsx and an element with several uses _jsxs, and the fragment is _Fragment. Your own import and your comment are kept as written. The layout is Babel’s, so the short destructured parameter spreads over three lines.

Classic or automatic JSX runtime: which one to pick

ClassicAutomatic
JSX becomesReact.createElement(type, props, ...children)jsx(type, props) or jsxs(type, props), with children inside props
Fragment becomesReact.Fragment_Fragment
Import addedNone. React must be in scopeimport { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime", with only the names the code uses
React versionAnyReact 17 or later
Pick it whenYour project or tutorial still imports React in every file, or you target an older setupYou want the output a current React toolchain would produce

What the output keeps and what it changes

What it does not do

It compiles JSX only. It does not read TypeScript, so TSX with type annotations is a syntax error, and it does not read Flow. It does not run your code, check that your components work, or bundle files. To go the other way, from plain JavaScript to typed code, use JS to TS Converter. To read minified or obfuscated scripts, use JS Deobfuscator.

Why it runs in your browser

Babel is loaded once, the first time you paste, and from then on the compiling happens in a Web Worker on your device. Your component is never sent anywhere, and it is never executed, so a file with side effects is safe to paste.


Frequently asked questions

How do I convert JSX to JS online?

Paste your JSX into the box labelled JSX code. About a third of a second later the compiled JavaScript appears under the heading JavaScript. There is no Convert button. Select Copy to clipboard to take the result. Babel downloads once, the first time you paste, so that first conversion takes a moment longer.

Does Babel convert JSX to JS?

Yes. Babel's React preset compiles JSX into JavaScript, and it is what this page runs, in your browser, so the output matches what a Babel build step gives you. Build tools do the same job automatically when you build a project. Use this page when you want to see or copy the result for a single component or snippet.

What is the difference between JS and JSX?

JSX is JavaScript with an XML-like syntax for describing UI, such as <button onClick={save}>Save</button>. Browsers cannot run it, so a compiler rewrites each tag into a plain function call. The result is ordinary JavaScript. A .jsx extension is only a naming convention for files that contain JSX.

What is the difference between classic and automatic runtime?

Classic turns JSX into React.createElement calls, so React must be in scope in every file that uses JSX. Automatic turns JSX into jsx() and jsxs() calls and adds an import from react/jsx-runtime for you, so you do not import React just to write JSX. Automatic needs React 17 or later. The default here is Classic.

How do I convert JSX to React.createElement?

Leave the JSX runtime on Classic, which is the default. Every element becomes a React.createElement call: the tag name first, then the props object (null when there are none), then the children. A fragment becomes React.Fragment.

Why does my output use React but never import it?

Classic output calls React.createElement and React.Fragment and does not add an import, because it assumes React is already in scope. If your file starts without import React from 'react', add that line, or switch the JSX runtime to Automatic, which writes the import it needs.

Why are there /*#__PURE__*/ comments in the output?

Babel puts /*#__PURE__*/ in front of each element call. It tells minifiers and bundlers that the call has no side effects, so an element that is never used can be dropped from the final bundle. You can leave the comments in or delete them. They do not change what the code does.

Can it convert TSX or TypeScript?

No. It expects JSX in plain JavaScript, so a type annotation such as props: Props is a syntax error. Remove the types first, or compile TypeScript with the TypeScript compiler. Flow syntax is not supported either.

What happens if my JSX has an error?

You see This is not valid JSX: syntax error at line N, column M. with the real numbers, followed by the offending line and a caret under the spot. No output is shown until the error is fixed. The limit is 1,000,000 characters.

Is my code uploaded or run?

No. Babel compiles the code in your browser, in a Web Worker, and nothing is sent to a server. The code is never executed either, so it is safe to paste a component with side effects. The only download is Babel itself, once.


Recommended

Helps keep the tools free. ✨

Images are for illustration only. As an Amazon Associate I earn from qualifying purchases.