
JSX!
JSXとは?なぜReactで使うのか
JSX(JavaScript XML)は、Reactアプリケーション開発において欠かせない技術の一つです。簡単に言うと、JavaScript の中でHTMLのようなマークアップを直接書ける拡張構文のことです。
従来のWeb開発では、HTML、CSS、JavaScriptを別々のファイルで管理していました。しかし、モダンなWebアプリケーションでは、ユーザーインターフェース(UI)の表示内容がJavaScriptのロジックに大きく依存するようになりました。
JSXを使用することで、以下のメリットが得られます:
- 視認性の向上:UIの構造とロジックを一箇所で確認できる
- 開発効率の向上:HTMLとJavaScriptを行き来する必要がない
- 型安全性:コンパイル時にエラーを検出しやすい
- 保守性:関連するコードがまとまっているため変更が容易
豆知識: JSXはFacebookの開発者が2013年にReactと共に発表しました。当初は「HTMLとJavaScriptを混ぜるのは良くない」という批判もありましたが、現在では多くの開発者に受け入れられています。
JSXの基本的な書き方
最もシンプルなJSXの例
まずは、最も基本的なJSXの書き方を見てみましょう:
function WelcomeMessage() {
return <h1>こんにちは、React初心者の皆さん!</h1>;
}
export default WelcomeMessage;
この例では、WelcomeMessage
という関数コンポーネントがJSXを返しています。一見するとHTMLそのものですが、実際はJavaScriptコードの一部です。
JSXの重要なルール
JSXを書く際には、HTMLとは異なる重要なルールがいくつかあります。
ルール1: 必ず単一の親要素で囲む
❌ 間違った書き方
function UserProfile() {
return (
<h2>田中太郎</h2>
<p>Web開発者</p>
);
}
✅ 正しい書き方
function UserProfile() {
return (
<div>
<h2>田中太郎</h2>
<p>Web開発者</p>
</div>
);
}
または、余分なDOMノードを作りたくない場合は、React.Fragment
(省略記法:<></>
)を使用します。
function UserProfile() {
return (
<>
<h2>田中太郎</h2>
<p>Web開発者</p>
</>
);
}
ルール2: すべてのタグは必ず閉じる
❌ HTML形式(JSXでは使えない)
<img src="profile.jpg" alt="プロフィール画像">
<input type="text" name="username">
✅ JSX形式
<img src="profile.jpg" alt="プロフィール画像" />
<input type="text" name="username" />
ルール3: 属性名はキャメルケースで記述
❌ HTML形式
<div class="profile-card">
<button onclick="handleClick()">クリック</button>
</div>
✅ JSX形式
<div className="profile-card">
<button onClick={handleClick}>クリック</button>
</div>
注意: class
はclassName
に、for
はhtmlFor
に変更する必要があります。これらはJavaScriptの予約語と衝突するためです。
HTMLからJSXへ変換
実際のHTMLをJSXに変換する過程を、ショッピングカードのコンポーネントを例に見てみましょう。
変換前のHTML
<div class="product-card">
<img src="https://example.com/laptop.jpg" alt="ノートパソコン">
<h3>高性能ノートパソコン</h3>
<p class="price">¥89,800</p>
<button class="add-to-cart" onclick="addToCart()">カートに追加</button>
</div>
変換後のJSX
function ProductCard() {
const handleAddToCart = () => {
console.log('カートに追加されました');
};
return (
<div className="product-card">
<img
src="https://example.com/laptop.jpg"
alt="ノートパソコン"
/>
<h3>高性能ノートパソコン</h3>
<p className="price">¥89,800</p>
<button
className="add-to-cart"
onClick={handleAddToCart}
>
カートに追加
</button>
</div>
);
}
export default ProductCard;
変更点の解説
class
→className
に変更<img>
タグに/>
を追加して自己完結タグにonclick
→onClick
に変更し、文字列ではなく関数を直接指定- 全体をReact関数コンポーネントとしてラップ
JSXでのJavaScript活用法(波括弧の使い方)
JSXの真価は、波括弧 {}
を使ってJavaScriptの式を埋め込めることにあります。これにより、動的なコンテンツを簡単に表示できます。
変数の表示
function UserGreeting() {
const userName = '佐藤花子';
const currentTime = new Date().toLocaleTimeString('ja-JP');
return (
<div>
<h2>{userName}さん、こんにちは!</h2>
<p>現在時刻: {currentTime}</p>
</div>
);
}
計算式の実行
function ShoppingCart() {
const itemPrice = 1200;
const quantity = 3;
const taxRate = 0.1;
return (
<div className="cart-summary">
<p>商品価格: ¥{itemPrice}</p>
<p>数量: {quantity}個</p>
<p>小計: ¥{itemPrice * quantity}</p>
<p>税込合計: ¥{Math.floor((itemPrice * quantity) * (1 + taxRate))}</p>
</div>
);
}
条件分岐による表示制御
function ProductStatus() {
const stockCount = 5;
const isOnSale = true;
return (
<div className="product-info">
<h3>商品在庫状況</h3>
{stockCount > 0 ? (
<p className="in-stock">在庫あり({stockCount}点)</p>
) : (
<p className="out-of-stock">在庫切れ</p>
)}
{isOnSale && <span className="sale-badge">セール中!</span>}
</div>
);
}
配列データの表示(リストレンダリング)
function RecommendedProducts() {
const products = [
{ id: 1, name: 'ワイヤレスマウス', price: 2980 },
{ id: 2, name: 'キーボード', price: 8900 },
{ id: 3, name: 'モニター', price: 24800 }
];
return (
<div className="recommended-products">
<h3>おすすめ商品</h3>
<ul>
{products.map(product => (
<li key={product.id}>
{product.name} - ¥{product.price.toLocaleString()}
</li>
))}
</ul>
</div>
);
}
重要: 配列をレンダリングする際は、必ず各要素に一意のkey
属性を設定してください。これによりReactが効率的に画面更新を行えます。
オブジェクトスタイルの適用
function StyledCard() {
const cardStyle = {
backgroundColor: '#f8f9fa',
border: '1px solid #dee2e6',
borderRadius: '8px',
padding: '20px',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
};
const titleStyle = {
color: '#495057',
fontSize: '24px',
marginBottom: '16px'
};
return (
<div style={cardStyle}>
<h2 style={titleStyle}>スタイル付きカード</h2>
<p>JSXでインラインスタイルを適用した例です。</p>
</div>
);
}
注意: CSS のプロパティ名はキャメルケースで記述します(例:background-color
→ backgroundColor
)。また、値は文字列またはオブジェクトとして指定します。
よくある間違いと解決法
「Objects are not valid as a React child」エラー
❌ エラーの原因
function UserInfo() {
const user = { name: '田中太郎', age: 30 };
return (
<div>
<p>ユーザー情報: {user}</p>
</div>
);
}
✅ 正しい書き方
function UserInfo() {
const user = { name: '田中太郎', age: 30 };
return (
<div>
<p>名前: {user.name}</p>
<p>年齢: {user.age}歳</p>
</div>
);
}
未定義値による表示エラー
❌ エラーが発生する可能性
function ProductPrice({ product }) {
return (
<p>価格: ¥{product.price}</p>
);
}
✅ 安全な書き方
function ProductPrice({ product }) {
return (
<p>
価格: ¥{product?.price || '価格未定'}
</p>
);
}
JSXでのコメントの書き方
function CommentExample() {
return (
<div>
{/* これはJSXコメントです */}
<h2>商品詳細</h2>
{/*
複数行のコメントも
このように書けます
*/}
<p>商品の説明文</p>
</div>
);
}
実践的な例:ショッピングカートコンポーネント
これまで学んだ内容を統合して、実用的なショッピングカートコンポーネントを作成してみましょう:
function ShoppingCartApp() {
const cartItems = [
{
id: 1,
name: 'プログラミング入門書',
price: 3200,
quantity: 1,
image: 'https://example.com/book1.jpg'
},
{
id: 2,
name: 'ワイヤレスキーボード',
price: 12800,
quantity: 2,
image: 'https://example.com/keyboard.jpg'
}
];
const calculateTotal = (items) => {
return items.reduce((total, item) => total + (item.price * item.quantity), 0);
};
const formatPrice = (price) => {
return price.toLocaleString();
};
const total = calculateTotal(cartItems);
const tax = Math.floor(total * 0.1);
const finalTotal = total + tax;
return (
<div className="shopping-cart">
<header>
<h1>🛒 ショッピングカート</h1>
<p>{cartItems.length}点の商品があります</p>
</header>
<main>
{cartItems.length === 0 ? (
<p className="empty-cart">カートに商品がありません</p>
) : (
<div className="cart-items">
{cartItems.map(item => (
<div key={item.id} className="cart-item">
<img
src={item.image}
alt={item.name}
className="item-image"
/>
<div className="item-details">
<h3>{item.name}</h3>
<p className="item-price">
¥{formatPrice(item.price)} × {item.quantity}個
</p>
<p className="item-subtotal">
小計: ¥{formatPrice(item.price * item.quantity)}
</p>
</div>
</div>
))}
</div>
)}
</main>
{cartItems.length > 0 && (
<footer className="cart-summary">
<div className="summary-row">
<span>商品合計:</span>
<span>¥{formatPrice(total)}</span>
</div>
<div className="summary-row">
<span>消費税:</span>
<span>¥{formatPrice(tax)}</span>
</div>
<div className="summary-row total">
<strong>
<span>合計:</span>
<span>¥{formatPrice(finalTotal)}</span>
</strong>
</div>
<button className="checkout-button">
レジに進む
</button>
</footer>
)}
</div>
);
}
export default ShoppingCartApp;
この例では以下のJSXテクニックを活用しています:
- 変数の埋め込み:商品名や価格の表示
- 関数の呼び出し:価格フォーマット、合計計算
- 条件分岐:空カートの場合の表示切り替え
- 配列レンダリング:商品一覧の表示
- 論理演算子:条件に応じたフッター表示
まとめと次のステップ
JSXマスターのポイント
この記事で学んだJSXの重要なポイントを振り返ってみましょう:
- 基本ルールの理解:単一親要素、タグの閉じ、キャメルケース
- 波括弧の活用:JavaScript式の埋め込み、動的コンテンツの表示
- 条件分岐とリスト:ユーザーインターフェースの動的制御
- エラー対策:よくある間違いとその回避方法
- 実践的な応用:複数のテクニックを組み合わせた実装
学習を続けるための次のステップ
JSXの基礎を理解したら、以下の内容に進むことをお勧めします:
- コンポーネント設計:再利用可能なコンポーネントの作成方法
- Props(プロパティ):コンポーネント間でのデータ受け渡し
- State(状態管理):動的なデータの管理とユーザーインタラクション
- イベントハンドリング:ユーザーアクションへの応答
- ライフサイクル:コンポーネントの生成・更新・破棄のタイミング
実践のすすめ: JSXは読むだけでなく、実際に手を動かして書くことで理解が深まります。CodeSandboxやCodePenなどのオンラインエディターで、今日学んだ例を改造してみることから始めてみてください。
おわりに
JSXは最初は HTML と JavaScript が混在することに戸惑うかもしれませんが、慣れてしまえば非常に直感的で効率的な記述方法です。この記事で紹介した基本をしっかりと身につけて、次のステップへと進んでみてください。
React の世界は奥が深く、JSX はその入り口に過ぎません。継続的な学習と実践を通じて、魅力的なWebアプリケーションを構築できるようになっていきましょう。