What actually happens when you click Format
This page runs your component through Prettier's babel parser, loaded from a CDN bundle straight into the page. The parser turns your code into an abstract syntax tree, a structured map of every import, hook call, prop, and JSX element, then Prettier reprints that tree using one consistent set of rules for line breaks, quotes, and indentation. That is a different process than a whitespace pass. A regex script can collapse extra spaces and guess at indentation, but it has no idea where one JSX element ends and the next prop starts. Parsing the real syntax means a deeply nested InvoiceSummary component with a .map() call inside a ternary formats the same way every time, regardless of how the original author indented it.
Everything runs in your browser tab. The bundle loads once from a CDN, then formatting happens locally with no network request carrying your code anywhere. That matters if the component you are formatting includes a real API endpoint, an internal hostname, or a customer's invoice number, none of it gets sent to a server for processing.
Parsing has one strict requirement your code has to be syntactically valid JavaScript or TypeScript with JSX. If a tag is left open or a brace is missing, the parser stops and reports the line where it lost track, rather than guessing at a fix. Read that error first. Formatting only ever changes whitespace and quoting, so if the output still looks broken after a successful format, the bug was already in the input.
This formatter will not touch your hooks logic
Formatting reflows lines, it does not reorder statements. A useEffect call stays exactly where you wrote it, before or after your other hooks, with the same dependency array contents. If two components render different output after formatting, look for a missing semicolon or an unintentional string concatenation in the original file, not this tool.
Where React formatting still trips people up
Most of the mistakes below survive formatting untouched, because they are logic problems wearing a whitespace disguise.
- Missing or unstable keys in
.map(). TheShoppingCartexample below renders a key fromitem.id. Swap that for the array index and React starts reusing DOM nodes across renders, which shows up as stale input values or flickering rows after a filter changes the list order. - Dependency arrays that lie about what a hook reads.
useEffect,useMemo, anduseCallbackall take an array of values the callback depends on. Formatting will neatly indent[userId]even when the callback also readsfilter, it has no way to know your function's logic changed. - JSX comments written the JavaScript way. A stray
// like thisinside a JSX children block renders as literal text on the page instead of disappearing. Inside markup, a comment needs braces:{}. - Ternaries nested inside JSX past two levels. One conditional inside a
returnreads fine. Two nested ternaries controlling the same element usually mean it is time to pull the branch into a small subcomponent or an early return, not to lean on the formatter for readability.
Function components, hooks, and old class components
The three examples loaded into the select box above cover the shapes of React code you will actually run into in an existing codebase. InvoiceSummary is a plain function component, no state, just props in and JSX out. ShoppingCart shows the hook pattern most new code follows, useState for local data, useCallback to keep a fetch function stable, useEffect to run it after mount. OrderHistory is a class component with a constructor, componentDidMount, and a bound instance method, the pattern most teams wrote before hooks existed and still have to maintain.
All three format the same way underneath, because a class component's render() method returns JSX just like a function component's return statement does. The visible difference is indentation depth: class components carry an extra level for the class body and another for the method, so the same JSX ends up nested one or two levels deeper on the page. That is expected, not a formatting inconsistency.
One rule this tool respects rather than enforces: hooks stay at the top level of a component and run in the same order on every render. Prettier's parser does not check that rule, it only reprints whatever order it finds. For that check, an editor's ESLint integration with eslint-plugin-react-hooks catches a conditional hook call before it reaches production, this page will format it cleanly and say nothing.
If your file mixes JSX with plain XML style markup outside of React, or you are formatting a template rather than a component, the JSX Formatter exposes indent size, quote style, and semicolon toggles as separate settings. This page skips that settings panel on purpose, most style debates are already settled once a repo picks Prettier defaults, and a second set of toggles here would just duplicate a page that already does that well.
What this formatter won't fix
Be clear about the boundary before you rely on this for a pull request.
- It will not catch a missing key prop, a stale dependency array, or a prop drilling problem three components deep. Those are lint and architecture issues, run
eslint-plugin-react-hooksalongside this page, not instead of it. - It will not repair broken JSX. An unclosed tag or a mismatched brace stops the parser cold, fix the reported line first, then format again.
- Very large files, several thousand lines in one component, parse slower here than they would in a build pipeline, because the work happens in your tab instead of on a server with more memory to spare.
- Flow type annotations are not supported. The babel parser reads TypeScript-style types, so a
.tsxfile formats fine, a Flow-annotated.jsfile usually does not.
The better approach treats formatting and linting as two separate steps in the same workflow. Format here before a review to remove whitespace noise from the diff, then let ESLint catch the logic issues that a formatter was never built to see. For a TypeScript-heavy file with complex generics, run it through the TypeScript Beautifier first, then bring the JSX back here.
React formatter questions
What this tool changes, what it leaves alone, and where it fits next to your existing lint setup.
Does this handle TypeScript React files, the .tsx ones?
Yes. The parser reads TypeScript syntax through Babel's TSX support, so interfaces, generics, and typed props format alongside the JSX in the same pass.
What happens if my component has a syntax error?
Formatting stops and the output panel shows the parser error along with a line number. Nothing partial gets written, fix the reported line in the input, then click Format again.
Will this reorder my hooks or my imports?
No. Statement order is preserved exactly as written, formatting only changes indentation, line breaks, and quote style. If hook order needs to change, that is a manual edit or an ESLint autofix, not something this page does.
Does it support class components as well as function components?
Both. The parser treats a class component's render method the same as a function component's return statement, the JSX inside gets identical formatting rules either way.
Is my code uploaded anywhere?
No. Parsing and formatting run in your browser after the Prettier bundle loads once from a CDN. Avoid pasting real API keys or customer data regardless, treat any browser tab the way you would treat a shared document.
Can I use this for Next.js, Remix, or a plain Vite React app?
Yes, the framework around a component does not change its JSX. Server components, client components, and standard hooks based components all use the same JSX and function syntax this parser reads.
