無料 HTML → JSX/React コンバーター
HTMLをReact互換のJSXに自動変換します。class→className、for→htmlFor、styleオブジェクト、イベントハンドラー、自己終了タグなどを処理します。
入力&出力
オプション
仕組み
- HTMLを貼り付け: 標準のHTMLスニペット, div、フォーム、テーブル、または完全なブロック, を入力エリアに入力します。
- オプションを選択: 必要に応じてReactフラグメントラッピングとプリティプリントフォーマットを有効にします。
- 瞬時にJSXを取得: コンバーターは自動的に
class→className、for→htmlForを変換し、style文字列をstyleオブジェクトに変換し、自己終了タグを閉じます。 - プロジェクトにコピー: JSX出力をReactコンポーネントに直接貼り付けます。
なぜHTML → JSXを使うのか?
HTMLテンプレートをReactに移行する場合、手動変換はエラーが発生しやすいです。1つのclassNameを忘れたり、未閉じのタグを残したりすると、ビルドが壊れます。このコンバーターは、属性内のbackground-colorのようなCSSプロパティ名をcamelCase backgroundColorに変換、イベントハンドラ文字列を関数参照に変換、void要素を適切に閉じるなど、必要なすべての変更を自動的に処理します。これにより、プロトタイピング、コード移行が高速化され、JSX構文の違いに不慣れな開発者を支援します。
主要な変換
- class → className, Reactコンポーネントで必要
- for → htmlFor, label要素用
- style文字列 → オブジェクト, 例:
"color:red"→{color:'red'} - 自己終了タグ,
<br>→<br /> - フラグメントラッピング, オプションの外側
<>…</>
JSXとは実際には何か
JSXは「JavaScript XML」の略だ。2013年にJSConf USで発表されたオリジナルのReactの一部としてFacebookのJordan Walkeが発明したJavaScriptへの構文拡張だ。JSXを使うと、JavaScriptコードの中に直接XMLライクなマークアップを書ける(<div className="hello">World</div>)。トランスパイラ(現在はほぼBabel)がそれをプレーンな関数呼び出しにコンパイルする(React.createElement('div', {className: 'hello'}, 'World'))。ブラウザが直接JSXを見ることはなく、出荷されるのは通常のJavaScriptだ。
Walkeの元々の動機は、テンプレート言語(Mustache、Handlebars、Angularの旧ディレクティブ)がホスト言語の第二級市民だったことにある。JavaScriptのループ、条件分岐、変数をネイティブに使えず、それぞれが独自のものを再発明していた。JSXは関係を逆転させた:テンプレートが時々JavaScriptを行うのではなく、JavaScriptが時々マークアップを行う。{condition && <Item />}がReact要素を返す通常のJS式であるという事実こそが根本的なアイデアだ。
React 17(2020年10月)以降、自動JSXランタイムによりJSXを使うすべてのファイルにimport React from 'react'を記述する必要はなくなった。Babelがランタイムのインポートを自動的に挿入するためだ。JSXはReact自体を超えて採用されている:Preact、Solid、Qwik、Hono JSX、Million、Lit、そしてTypeScriptの.tsxはすべて同じ構文を使用する。facebook.github.io/jsxのJSXドラフト仕様は意図的にフレームワーク非依存だ。
HTML→JSXの相違点一覧
- 予約語のリネーム。
class→className(classはJSの予約語のため)。for→htmlFor(同様の理由。forはループキーワード)。これが誰もが最初につまずく2つだ。 - その他すべての属性はcamelCase。
tabindex→tabIndex、readonly→readOnly、maxlength→maxLength、contenteditable→contentEditable。 - ケバブケースを保持する重要な2つの例外。
aria-*属性(aria-label、aria-hidden)とdata-*属性(data-testid)はHTML形式を保つ。xmlnsも同様。 - void要素では自己閉じタグが必須。
<br>は<br />に、<img>は<img />に、<input>は<input />になる。HTMLは寛容だがJSXはXML厳格だ。 - インラインスタイルは文字列ではなくオブジェクトを取る。
style="color: red; background-color: blue"はstyle={{ color: 'red', backgroundColor: 'blue' }}になる。3点に注意:二重波括弧(外側がJSX式、内側がオブジェクトリテラル)、camelCaseのプロパティ名、クォートされた文字列値。数値のピクセル値は単位を省略する:marginTop: 16であって'16px'ではない。 - イベントハンドラーはcamelCaseで関数参照を取る。
onclick="handleClick()"はonClick={handleClick}になる:括弧がないことに注意。onClick={handleClick()}はレンダリング時にhandleClickを呼び出し、戻り値をハンドラーとして割り当ててしまう。これはほぼ常にバグだ。 - コメントはJSX内で
{/* … */}を使う。<!-- … -->のHTMLコメント構文はJSX内では意味を持たない。 - フラグメントで複数の兄弟要素をラップする。コンポーネントは単一のルートを返す必要があるため、複数のトップレベル要素は
<>…</>(または長い形式の<React.Fragment>…</React.Fragment>)で囲む必要がある。 - 条件付きレンダリングにはJS式を使う。
{isVisible && <Item />}は条件がtruthyの場合のみアイテムをレンダリングする。{condition ? <A /> : <B />}は2つのうちどちらか一方を選択する。 - テキスト内の波括弧はエスケープが必要。JSXテキストコンテンツ内のリテラル
{は式の開始として解釈される。{'{'}またはHTML実体参照の同等物を使用すること。
SVG、アクセシビリティ、その他
SVGはJSX内でほとんどの属性に同じcamelCaseルールで動作する:viewBox、strokeWidth、fillOpacity。注目すべき例外:xlink:hrefは特別なxlinkHrefスペリングを使用する(現在はプレーンなhrefを優先して非推奨)。xmlnsはそのまま。アクセシビリティ属性はARIA自身のケバブケース規則に従う例外として:aria-label、aria-describedby、roleはすべて記述通り。
CSSについては、JSXのインラインstyleオブジェクトが1つの選択肢だ。ほとんどの本番コードベースは3つのより豊かな代替手段のいずれかを使用する:CSS Modules(バンドラーによってコンパイルされたファイルごとのスコープ付きクラス名)、Tailwind CSS(classNameを通じてクリーンにパスするユーティリティクラス)、またはCSS-in-JSライブラリ(styled-components、Emotion、Vanilla Extractなど)。Tailwindは2022年以降の新プロジェクトで最も一般的な選択肢になった。TailwindクラスはHTMLからJSXへの移行時にまったく変換が不要で、通常のclassName文字列としてそのままパスする。
よくある変換の落とし穴
- 関数を呼び出すインラインイベントハンドラー。HTMLの
onclick="alert(1)"はJSXでは通常onClick={() => alert(1)}(クリック時にalertが発火するようアロー関数でラップ)になる。onClick={alert(1)}を生成する単純なコンバーターはクリック時ではなくレンダリング時にalertをポップアップする。このコンバーターは一般的なケースを処理するが、出力を目視で確認する価値がある。 - HTMLコメントは削除される。ほとんどのJSXコンバーターはHTMLコメントを
{/* */}形式に変換するのではなく削除する。後者はJSX内の特定の位置でのみ機能するためだ。必要な場所にコメントを手動で追加すること。 - SVG属性のリネームは自動コンバーターでは常に処理されるわけではない。
stroke-width、fill-rule、clip-path、text-anchorはすべてcamelCase形式が必要だ。HeroiconsやLucideのようなアイコンセットからSVGを貼り付ける場合は出力を注意深くチェックすること。 - Boolean属性。HTMLの
<input disabled>はJSXで<input disabled />になる。HTMLの<input disabled="false">は実際にはdisabledになる(任意の値で有効化される)が、JSXのdisabled={false}は正しくオフだ。JSXのセマンティクスはHTMLより理にかなっている。 - HTMLエンティティ。
©はJSXテキストコンテンツで機能するが、リテラルのUnicode文字(©)を使用する方が好ましい。 も同様に機能する。 - tabindexの注意点。
tabindexはtabIndexにすべきだ。値が0や-1のように数値に見えることが多いため忘れやすいが、属性名はやはりcamelCaseが必要だ。
このツールを使う場面
- サーバーレンダリングされたテンプレートをReactに移行する。既存サイトのHTMLを貼り付けてJSXを得るのが典型的なユースケースだ。
- アイコン、バッジ、デザインツールのエクスポートを取り込む。Heroicons、Lucide、Figmaの「SVGとしてコピー」はすべてリネームパスが必要な生のHTML/SVGを提供する。
- Tailwind UI / Flowbite / DaisyUIのスニペットをHTML例からReactプロジェクト用のJSXに変換する。Tailwindクラスは変更なしにパスする。構造的な属性のみが変換を必要とする。
- HTMLは知っているがJSXを知らない開発者のオンボーディング。機械的なルールが自動的に適用されるのを見ることは、相違点リストを読むより早い。
- クイックプロトタイピング。スケッチ目的でプレーンHTMLでマークアップを下書きしてReactコンポーネントの中に入れたいとき。
出力はあらゆるJSXコンシューマー(React、Preact、Solid、Qwik、Hono JSX、Million、Litのhtmlテンプレートリテラル、細かい調整は必要)で機能する。React Nativeには対応していない。React Nativeは<View>や<Text>のようなネイティブプリミティブコンポーネントを使用するためHTMLエレメントではない。
その他の質問
JSXとHTMLの違いは何か?
HTMLはブラウザが直接パースするマークアップ言語だ。JSXはReact.createElement呼び出しにコンパイルされるJavaScriptの式構文であり、JSXとしてブラウザに届くことは決してない。JSXはXML厳格に見える(すべてのタグを閉じる必要があり、属性はcamelCaseを使用)。それはJavaScript式としてパースされるためで、寛容なHTMLとしてではない。視覚的な類似性は意図的だが、根本的なセマンティクスはかなり異なる。
JSXファイルすべてでReactをインポートする必要はまだあるか?
React 17(2020年10月)からは不要だ。自動JSXランタイムが導入され、Babelが必要なランタイムインポートを挿入するため、JSXのみを使用するファイルにはファイル先頭のimport React from 'react'が不要になった。クラシックランタイムは古いツールチェーン向けにまだ利用可能だ。ほとんどの新しいプロジェクトは自動ランタイムを使用する。
ReactなしでJSXを使えるか?
はい。JSXはfacebook.github.io/jsxにドラフト仕様を持つ汎用構文であり、多くのフレームワークがそれを使用する:Preact、Solid、Qwik、Hono JSX、Million、Lit、そしてhtmタグ付きテンプレートバリアント。フレームワークはJSXのコンパイル先(Preactはh(…)を使用、Solidはきめ細かいリアクティブプリミティブにコンパイル、など)は異なるが構文は共有されている。
なぜスタイルは文字列ではなくオブジェクトを取るのか?
JSXの式構文がJavaScriptの値を埋め込むための波括弧をすでに提供しており、オブジェクトリテラルがプロパティバッグの最も自然なJS表現であるためだ。スタイルオブジェクトは数値(ほとんどが自動的にpxになる)とJS式も許可するが、文字列ではできない。トレードオフは少し扱いにくい二重波括弧のstyle={{ … }}構文だ。外側の波括弧は「これはJSX式」を意味し、内側の波括弧はオブジェクトリテラルを表す。
何かサーバーに送信されるか?
いいえ。変換ロジックはHTMLの文字列を走査して属性を書き換える純粋なJavaScriptで、すべてブラウザ内で実行される。貼り付けたHTMLはページから出ることはない。独自の内部テンプレートやAPIエンドポイントが組み込まれたコンポーネントマークアップを移行する際に役立つ。