HTMLからJSXへの変換とは?
HTMLからJSXへの変換は、標準的なHTMLマークアップをReactコンポーネントがレンダリングできるJSX構文に変換するプロセスです。JSXはHTMLに似ていますが、JavaScriptの命名規則とルールに従います。classはclassNameに、forはhtmlForに変換され、インラインスタイル文字列はJavaScriptオブジェクトに置き換えられます。これらの変更が必要なのは、JSXがReact.createElement()の呼び出しにコンパイルされるためで、属性名はHTML属性名ではなくDOM APIのプロパティ名と一致する必要があります。
HTML属性とJSX propsのマッピングは、ReactのDOM要素ドキュメントで定義されています。Reactは複数単語の属性にcamelCaseを使用します(tabindexはtabIndex、maxlengthはmaxLengthになります)。これはJavaScriptの識別子にハイフンを含めることができないためです。<img>、<br>、<input>などの自己閉じタグはJSXでは末尾のスラッシュが必要です(<img />)。JSXはすべてのタグを明示的に閉じる必要があるXMLのルールに従うためです。
属性名の変換に加え、HTMLからJSXへの変換はインラインスタイルとコメントも処理します。HTMLのstyle属性はCSS構文を文字列として使用します(style="color: red; font-size: 14px")が、JSXはcamelCaseのプロパティ名を持つJavaScriptオブジェクトを必要とします(style={{ color: 'red', fontSize: '14px' }})。HTMLコメント(<!-- -->)はJSXの式コメント({/* */})になります。これらの変換を見落とすと、Reactアプリケーションで実行時エラーまたは予期しないレンダリングバグが発生します。
HTML to JSXコンバーターを使う理由
数十のHTML要素にわたって属性を手動で書き換え、スタイル文字列を変換するのは時間がかかりミスが起きやすい作業です。コンバーターはすべての変換を一度に処理し、任意のソースからHTMLを貼り付けて数秒で有効なJSXを取得できます。
HTML to JSXの活用例
HTML→JSX属性マッピングリファレンス
下の表はJSXに変換したときに変わるHTML属性の一覧です。ここに記載されていない属性(id、src、href、alt、placeholderなど)は、HTMLの名前がDOM APIのプロパティ名と既に一致しているため変更されません。
| HTML属性 | JSX Prop | 備考 |
|---|---|---|
| class | className | Reserved word in JavaScript |
| for | htmlFor | Reserved word in JavaScript |
| tabindex | tabIndex | camelCase convention |
| readonly | readOnly | camelCase convention |
| maxlength | maxLength | camelCase convention |
| minlength | minLength | camelCase convention |
| cellpadding | cellPadding | camelCase convention |
| cellspacing | cellSpacing | camelCase convention |
| rowspan | rowSpan | camelCase convention |
| colspan | colSpan | camelCase convention |
| enctype | encType | camelCase convention |
| autocomplete | autoComplete | camelCase convention |
| autofocus | autoFocus | camelCase convention |
| autoplay | autoPlay | camelCase convention |
| contenteditable | contentEditable | camelCase convention |
| crossorigin | crossOrigin | camelCase convention |
| novalidate | noValidate | camelCase convention |
| allowfullscreen | allowFullScreen | camelCase convention |
| spellcheck | spellCheck | camelCase convention |
| http-equiv | httpEquiv | Hyphen removed, camelCase |
| onclick | onClick | Event handler camelCase |
| onchange | onChange | Event handler camelCase |
| onsubmit | onSubmit | Event handler camelCase |
インラインスタイルの変換:HTML vs JSX
インラインスタイルはHTMLからJSXへの変換で最もミスが起きやすい部分です。値の形式とプロパティ名の両方が変わるためです:
<div style="background-color: #fff; font-size: 14px; margin-top: 10px;">
<div style={{
backgroundColor: '#fff',
fontSize: '14px',
marginTop: 10
}}>コード例
さまざまな言語と環境でHTMLをJSXにプログラムで変換する方法を示します。属性名の変換、スタイルの変換、自己閉じタグの処理をそれぞれカバーしています。
// Simple attribute conversion using string replacement
function htmlToJsx(html) {
return html
.replace(/\bclass=/g, 'className=')
.replace(/\bfor=/g, 'htmlFor=')
.replace(/\btabindex=/g, 'tabIndex=')
.replace(/<!--([\s\S]*?)-->/g, '{/*$1*/}')
}
htmlToJsx('<div class="box" tabindex="0"><!-- note --></div>')
// → '<div className="box" tabIndex="0">{/* note */}</div>'import parse from 'html-react-parser'
// Parse HTML string into React elements (handles all JSX rules)
const element = parse('<div class="card"><img src="photo.jpg" alt="Photo"></div>')
// Returns: React.createElement('div', { className: 'card' },
// React.createElement('img', { src: 'photo.jpg', alt: 'Photo' }))
// With custom element replacement
const options = {
replace(domNode) {
if (domNode.name === 'img') {
return <OptimizedImage src={domNode.attribs.src} alt={domNode.attribs.alt} />
}
}
}
const custom = parse('<img src="photo.jpg" alt="Photo">', options)from bs4 import BeautifulSoup
import re
ATTR_MAP = {
'class': 'className', 'for': 'htmlFor',
'tabindex': 'tabIndex', 'readonly': 'readOnly',
'maxlength': 'maxLength', 'autocomplete': 'autoComplete',
}
def html_to_jsx(html: str) -> str:
"""Convert HTML attribute names to JSX equivalents."""
for html_attr, jsx_attr in ATTR_MAP.items():
html = re.sub(rf'\b{html_attr}=', f'{jsx_attr}=', html)
# Convert HTML comments to JSX comments
html = re.sub(r'<!--(.*?)-->', r'{/*\1*/}', html)
return html
print(html_to_jsx('<label for="email" class="field">Email</label>'))
# → '<label htmlFor="email" className="field">Email</label>'package main
import (
"fmt"
"strings"
)
var attrMap = map[string]string{
"class=": "className=",
"for=": "htmlFor=",
"tabindex=": "tabIndex=",
"readonly": "readOnly",
}
func htmlToJSX(html string) string {
result := html
for old, new := range attrMap {
result = strings.ReplaceAll(result, old, new)
}
// Convert comments
result = strings.ReplaceAll(result, "<!--", "{/*")
result = strings.ReplaceAll(result, "-->", "*/}")
return result
}
func main() {
html := `<div class="wrapper"><input readonly tabindex="1"></div>`
fmt.Println(htmlToJSX(html))
// → <div className="wrapper"><input readOnly tabIndex="1"></div>
}