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
- Paste your code into JSX code. The box reads Paste JSX here… until you do. The limit is 1,000,000 characters.
- 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.
- Read the result under the heading JavaScript. It is shown as read-only highlighted code.
- Select Copy to clipboard. The button changes to Copied.
- 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:
With Classic, the default, the converter writes this:
With Automatic, it writes this:
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
| Classic | Automatic | |
|---|---|---|
| JSX becomes | React.createElement(type, props, ...children) | jsx(type, props) or jsxs(type, props), with children inside props |
| Fragment becomes | React.Fragment | _Fragment |
| Import added | None. React must be in scope | import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime", with only the names the code uses |
| React version | Any | React 17 or later |
| Pick it when | Your project or tutorial still imports React in every file, or you target an older setup | You want the output a current React toolchain would produce |
What the output keeps and what it changes
- Imports and exports stay as you wrote them.
- Comments stay, in the place they were.
- Plain JavaScript around the JSX is left as it is, apart from Babel’s layout.
- Formatting is Babel’s, not Prettier’s: your quotes and line breaks in the JSX are not kept. To tidy the result, run it through Code Formatter.
- /*#__PURE__*/ annotations are added in front of element calls. They tell bundlers the call has no side effects.
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
-
Desktop Magnetic Whiteboard with MarkersSketch the component tree and see which createElement call nests inside which.
-
KYY 15.6" Portable MonitorKeep the tutorial or docs on a second screen while you compare your JSX with its output.
-
Quntis Monitor Light BarLights the desk, not the screen, for late-night debugging sessions.
Helps keep the tools free. ✨
Images are for illustration only. As an Amazon Associate I earn from qualifying purchases.