JSXを理解したい
ReactのコンポーネントをつくるJSXはどんなものなのかをまとめてみます。
JSXとはなにか
JSX(JavaScript XML)はJavaScriptの中にHTMLっぽい構文を書ける拡張構文です。
TSXはそのTypeScript版ですね。
function Welcome() {
return <h1>Hello, React!</h1>;
}
JSX と React は別の物です。一緒に使われることが多いですが、片方だけを独立して使うことは可能です。JSX とは言語の拡張であり、React は JavaScript ライブラリです。
JSXはReactとともに発表されましたが、Reactの公式にもあるとおり、React専用というわけではありません。他のフレームワーク・ライブラリでも採用されているようです。
JSXはJavaScriptに変換される
JSXは、ビルドツール(Viteのesbuildなど)によって普通のJavaScriptに変換されます。
// JSXで書いたコード
const element = <h1>Hello!</h1>;
// ↓ ビルドツールが変換
// 実際のJavaScript
const element = React.createElement('h1', null, 'Hello!');
なぜJSXを使うのか
JSXなしで仮想DOMを作成する場合、とてもわかりづらくなります。
// JSXなし(React.createElement)
const element = React.createElement(
'div',
{ className: 'container' },
React.createElement('h1', null, 'タイトル'),
React.createElement('p', null, '説明文')
);
しかし、JSXだとHTMLとほぼ同じなのでHTMLを知っていればすぐに理解できます。
// JSXあり
const element = (
<div className="container">
<h1>タイトル</h1>
<p>説明文</p>
</div>
);
また、HTMLタグの中に直接JavaScriptを埋め込んで変数の内容を表示することもできます。
const name = "太郎";
const element = <h1>こんにちは、{name}さん!</h1>;
// <h1>こんにちは、太郎さん!</h1>
jQueryの全盛期などは、マークアップ言語のHTMLに構造を記述し、CSSでスタイリングし、DOM操作などをする役割でJavaScriptファイルがありました。
この場合、HTMLとJavaScriptが分離しているため、コンテンツの管理が複雑になりがちです。
// ❌ jQuery時代:HTMLとJavaScriptが完全に分離
// HTML
<div id="user-info">
<h2 id="user-name"></h2>
<p id="user-email"></p>
<span id="user-role"></span>
</div>
// JavaScript
const user = {
name: '田中太郎',
email: 'tanaka@example.com',
role: 'admin'
};
// データをHTMLに反映するコード
$('#user-name').text(user.name);
$('#user-email').text(user.email);
$('#user-role').text(user.role);
それに比べて、JSXは1つのファイルで完結できるため、全体像が一目でわかるようになりました。
// ✅ JSX時代:データと表示が1箇所にまとまる
const user = {
name: '田中太郎',
email: 'tanaka@example.com',
role: 'admin'
};
// JSXでデータと表示を一体化
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
<span>{user.role}</span>
</div>
条件分岐
returnの中に、直接if文は使えませんが、三項演算子、論理演算子などを使うことで行うことができ、条件に応じた異なるUIを表示することができます。(returnの前にifを使うことはできます)
これにより、「この条件のときはこれが表示される」というロジックがわかりやすく表現できます。
// 1. 論理演算子(&&)- 単純な条件
{hasNewMessage && <p>新しいメッセージがあります</p>}
// 2. 三項演算子 - true/false両方を表示
<span style={{ color: user.isPremium ? 'gold' : 'gray' }}>
{user.isPremium ? 'プレミアム会員' : '一般会員'}
</span>
// 3. return前にif文を書く - 複雑な分岐
function UserStatus({ user }) {
let statusElement;
if (user.isOnline) {
statusElement = <span style={{ color: 'green' }}>オンライン</span>;
} else if (user.isAway) {
statusElement = <span style={{ color: 'yellow' }}>離席中</span>;
} else {
statusElement = <span style={{ color: 'gray' }}>オフライン</span>;
}
return <div>{statusElement}</div>;
}
繰り返し
LPなどのWeb制作をやられていた方は経験があるかと思いますが、カードなどの同じ構造でちょっと内容が違う場合もHTMLだけの場合は、10個あれば10個分のコードを記述しなければいけません。
そのため、コピペすることになりますが、修正時に変更されていないなんてことはよくあることかと思います。
JSXはHTMLの中にmap()などで繰り返し処理をすることができ、コンポーネントとして管理することもできるため修正漏れなどが起こりにくくなります。
function ProductCard({product}) {
return (
<div className="card">
<img src={product.image} alt={product.title} />
<h3>{product.title}</h3>
<p>{product.description}</p>
<button onClick={() => handleBuy(product.id)}>購入</button>
</div>
);
}
// 使う側
const products = [
{ id: 1, image: 'image1.jpg', title: '商品1', description: '説明文1' },
{ id: 2, image: 'image2.jpg', title: '商品2', description: '説明文2' }
];
<div>
{products.map(product => (
<ProductCard key={product.id} product={product} />
))}
</div>
JSXの基本構文
基本的な書き方
JSXはfunction宣言でもアロー関数でも書くことができます。
function Greeting() {
return <h1>Hello, World!</h1>;
}
const Greeting = () => {
return <h1>Hello, World!</h1>;
}
複数行の場合は()で囲む
複数行のJSXを見やすくしどこからどこまでを返すのかがわかりやすくなります。
function Greeting() {
return (
<div>
<h1>Hello</h1>
<p>Welcome to React</p>
</div>
);
}
コンポーネント名は大文字からはじめる
コンポーネント名はHeaderなど、大文字からはじめる必要があります。
そうしないとコンポーネントと認識されません。
// ❌ 小文字で始まる
function header() {
return <h1>ヘッダー</h1>;
}
// JSXで使う
<header /> // HTMLのheaderタグとみなされる
// ✅ 大文字で始める
function Header() {
return <h1>ヘッダー</h1>;
}
// JSXで使う
<Header /> // Reactコンポーネントとして認識される
JavaScriptの式を{}で埋め込む
式とは値を返すものです。
{name}
{age + 1}
{isLoggeIn ? "ログイン済み" : "ログインしていない"}
{user.name}
{calculate()}
値を返さないif文やfor文は使えません。
そのため、Reactではmap()や三項演算子を見る機会が多いです。
複数の要素を返す時はラッパー要素かフラグメントで包む
JavaScriptの関数は1つの値しか返せません。
そのため以下のコードの場合エラーとなります。
function Header() {
return (
<h1>タイトル</h1>
<p>サブタイトル</p>
);
}
divタグなどで囲むか、余計なタグを入れたくない場合はフラグメントで囲みます。
function Header() {
return (
<div>
<h1>タイトル</h1>
<p>サブタイトル</p>
</div>
);
}
function Header() {
return (
<>
<h1>タイトル</h1>
<p>サブタイトル</p>
</>
);
}
オブジェクトは直接埋め込まない
あまりないとは思いますが、オブジェクトは直接埋め込めません。オブジェクトのプロパティは埋め込めます。
// ❌ エラー
function Component() {
const user = { name: '太郎', age: 25 };
return <div>{user}</div>; // オブジェクトは直接埋め込めない
}
// ✅ 解決方法
function Component() {
const user = { name: '太郎', age: 25 };
return <div>{user.name}</div>; // プロパティを埋め込む
}
HTMLとJSXの違い
JSXはHTMLによく似ていますが、いくつか癖があります。
classは使えない。classNameを使う
classはJavaScriptの予約語です。HTMLのclassを使いたい場合はclassNameを使います。
// ❌ HTML(JSXでは使えない)
<div class="container">...</div>
// ✅ JSX
<div className="container">...</div>
forは使えない。htmlForを使う
forも予約語です。HTMLのforを使いたい場合はhtmlForを使います。
// ❌ HTML(JSXでは使えない)
<label for="email">メール</label>
// ✅ JSX
<label htmlFor="email">メール</label>
属性名はキャメルケース
HTMLの属性名は、JSXではキャメルケースで書きます。
// HTML
<button onclick="handleClick()">クリック</button>
<input onchange="handleChange()" />
<div tabindex="0">...</div>
// JSX
<button onClick={handleClick}>クリック</button>
<input onChange={handleChange} />
<div tabIndex="0">...</div>
インラインスタイルのプロパティ名はキャメルケース
インラインスタイルでCSSを充てる場合はキャメルケースになります。
function ColoredText() {
return (
<p style={{ color: 'red', fontSize: '20px' }}>
赤い文字
</p>
);
}
自己閉じタグが必須
HTMLでは省略できるタグもJSXでは必ず閉じる必要があります。
// ❌ HTML(JSXではエラー)
<img src="logo.png">
<input type="text">
<br>
// ✅ JSX
<img src="logo.png" />
<input type="text" />
<br />
属性値は文字列かJavaScriptの式で
// ✅ 正しい
<input type="text" maxLength={10} />
<img src={imageUrl} alt="画像" />
<div style={{ color: 'red' }}>...</div>
// ❌ 間違い
<input maxLength=10 /> // 数値は{}で囲む
リストのレンダリング
JSXではリストのレンダリングはforループを使えないため、map()メソッドを使うことが多いです。
function ProductList() {
const products = [
{ id: 101, name: '商品A', price: 1000 },
{ id: 102, name: '商品B', price: 2000 },
{ id: 103, name: '商品C', price: 3000 }
];
return (
<ul>
{products.map(product => (
<li key={product.id}>
{product.name}: ¥{product.price}
</li>
))}
</ul>
);
}
Reactでは、リスト内の各要素を一意に識別するためにkeyが必須です。
keyに使うべき値:
- ✅ 各要素に対して一意で安定したID(product.idなど)
- ❌ indexは避けるべき - リストの順序が変わると問題が発生します
keyが異なると、Reactは異なる要素と判断し、不要な再レンダリングや状態管理の不具合が起こる可能性があります。
まとめ
JSXについてまとめてみました。
HTMLと似ているので、Reactコンポーネントの作成が使わない場合(ないですけど)より楽になりますね。
JSXの主な利点
- 可読性の向上 - HTMLに似た構文で理解しやすい
- データと表示の統合 - 1つのファイルで完結
- 動的なUI - JavaScriptの式を直接埋め込み可能
- 保守性の向上 - コンポーネント化で修正漏れを防止
重要なポイント
- 変換される仕組み - ビルド時にReact.createElementに変換
- 基本ルール - 大文字開始、単一要素返却、{}で式埋め込み
- HTMLとの違い - className、htmlFor、キャメルケース属性
- リスト表示 - map()とkey属性の重要性
学習のお役に立てたらうれしいです。
ありがとうございました。