Chapter 01

JSX を理解しよう

JavaScriptの中にHTMLを書ける構文「JSX」の仕組みと書き方を学びます。

30 min

このチャプターで学ぶこと

  • JSXがJavaScriptの糖衣構文であることを理解できる
  • HTMLとJSXの違い(className、htmlFor など)を説明できる
  • 波括弧 {} を使って動的な値を埋め込める
  • フラグメント <></> を使って複数要素を返せる
  • 自己紹介カードをJSXで作れる

JSX を理解しよう

前のチャプターでは App.jsx の中にHTMLのようなコードが書かれているのを見ました。あれは JSX という構文です。このチャプターでJSXをしっかり理解しておきましょう。

JSXとは何か

JSXは「JavaScript XML」の略で、JavaScriptの中にHTMLライクな構文を書けるようにした拡張機能です。

// これがJSX
const element = <h1>こんにちは</h1>;

見た目はHTMLですが、実際にはJavaScriptです。Viteなどのビルドツールが、このJSXを通常のJavaScript関数呼び出しに変換します。

// ビルド後のJavaScript(実際には人間が書かなくてよい)
const element = React.createElement('h1', null, 'こんにちは');

React.createElement を毎回手書きするのは大変なので、JSXという便利な構文が生まれました。Laravelのbladeテンプレートが最終的にHTMLに変換されるのと似た仕組みです。

📝 メモ

JSXを使うために特別なインポートは不要です(React 17以降)。Viteのテンプレートは最初からJSXが使えるように設定されています。

HTMLとJSXの違い

JSXはHTMLとよく似ていますが、いくつか重要な違いがあります。ここをしっかり覚えておかないとエラーの原因になります。

1. class ではなく className

HTMLでは要素にクラスを付けるとき class を使います。しかしJavaScriptでは class は予約語(classの定義に使う)なので、JSXでは className を使います。

// HTML
<div class="container">...</div>

// JSX(正しい書き方)
<div className="container">...</div>

2. for ではなく htmlFor

<label>for 属性も同様に、for がJavaScriptの予約語(forループ)なので htmlFor に変わります。

// HTML
<label for="email">メールアドレス</label>
<input id="email" type="email" />

// JSX(正しい書き方)
<label htmlFor="email">メールアドレス</label>
<input id="email" type="email" />

3. 自己閉じタグが必須

HTMLでは <input><img> は閉じタグなしで書けますが、JSXでは必ずスラッシュで閉じる必要があります。

// HTML(これはOK)
<input type="text">
<img src="photo.jpg" alt="写真">
<br>

// JSX(必ずスラッシュで閉じる)
<input type="text" />
<img src="photo.jpg" alt="写真" />
<br />

4. スタイルはオブジェクトで書く

インラインスタイルを書く場合、JSXではCSSの文字列ではなくJavaScriptオブジェクトを使います。プロパティ名はキャメルケースになります。

// HTML
<p style="color: red; font-size: 16px;">テキスト</p>

// JSX
<p style={{ color: 'red', fontSize: '16px' }}>テキスト</p>

外側の {} はJSXに式を埋め込む記号、内側の {} はJavaScriptオブジェクトのリテラルです。

⚠️ 注意

font-size のようにハイフン区切りのCSSプロパティは、JSXでは fontSize のようなキャメルケースに変換します。background-colorbackgroundColorborder-radiusborderRadius といった具合です。

式を埋め込む {}

JSXの中で波括弧 {} を使うと、JavaScriptの式を埋め込めます。これがJSXの最も便利な機能です。

function Greeting() {
  const name = '山田太郎'
  const currentYear = new Date().getFullYear()

  return (
    <div>
      {/* 変数を表示 */}
      <h1>こんにちは、{name}さん!</h1>

      {/* 計算結果を表示 */}
      <p>今年は{currentYear}年です</p>

      {/* 三項演算子で条件分岐 */}
      <p>{name.length > 3 ? '長い名前ですね' : '短い名前ですね'}</p>
    </div>
  )
}

{} の中には を書きます。if文for文 などの は直接書けません。条件分岐には三項演算子 ? :&& 演算子を使います。

function StatusBadge() {
  const isLoggedIn = true

  return (
    <div>
      {/* && 演算子:左辺がtrueのときだけ右辺をレンダリング */}
      {isLoggedIn && <span>ログイン中</span>}

      {/* 三項演算子:条件によって表示を切り替え */}
      <p>{isLoggedIn ? 'ようこそ!' : 'ログインしてください'}</p>
    </div>
  )
}
💡 ヒント

JSXのコメントは {/* コメント */} と書きます。HTMLの <!-- --> やJavaScriptの // はJSXの中では使えません(属性値の外のJavaScript部分では // が使えます)。

配列のレンダリング

map() を使うと配列をJSXのリストに変換できます。これはよく使うパターンです。

function FruitList() {
  const fruits = ['りんご', 'バナナ', 'みかん']

  return (
    <ul>
      {fruits.map((fruit) => (
        // key はReactが差分を効率よく計算するために必要
        <li key={fruit}>{fruit}</li>
      ))}
    </ul>
  )
}
⚠️ 注意

map() でリストをレンダリングするときは、各要素に必ず key 属性を付けてください。key はリスト内で一意な文字列または数値である必要があります。key を省略するとコンソールに警告が表示されます。

フラグメント <>...</>

Reactのコンポーネントは 必ず1つのルート要素 を返す必要があります。複数の要素を返したいとき、余分な <div> で囲むとHTMLの構造が汚れてしまいます。そこで使うのが フラグメント です。

// NG: 複数の要素をそのまま返せない
function Bad() {
  return (
    <h1>タイトル</h1>
    <p>本文</p>  // SyntaxError!
  )
}

// OKだがHTMLに余分なdivが増える
function WithDiv() {
  return (
    <div>
      <h1>タイトル</h1>
      <p>本文</p>
    </div>
  )
}

// ベスト:フラグメントを使う
function WithFragment() {
  return (
    <>
      <h1>タイトル</h1>
      <p>本文</p>
    </>
  )
}

フラグメント <> は実際のDOMには何も追加しません。HTMLを余計な要素で汚さずに複数の要素をグループ化できます。

📝 メモ

<><React.Fragment> の短縮記法です。key 属性を付けたい場合(リスト内など)は <React.Fragment key={id}> と書く必要があります。

属性に動的な値を渡す

属性値にも {} を使って動的な値を渡せます。

function UserAvatar() {
  const userName = '山田太郎'
  const avatarUrl = 'https://example.com/avatar.jpg'
  const isActive = true

  return (
    <div>
      {/* 文字列以外の値はすべて {} で渡す */}
      <img
        src={avatarUrl}
        alt={`${userName}のアバター`}
        width={64}
        height={64}
      />
      {/* 条件によってクラスを切り替える */}
      <span className={isActive ? 'status active' : 'status inactive'}>
        {isActive ? 'オンライン' : 'オフライン'}
      </span>
    </div>
  )
}
✍ やってみよう:自己紹介カードを作る

src/App.jsx を編集して、自己紹介カードを作ってみましょう。以下の要件を満たしてください:

  1. 名前を変数 name に入れて {} で表示する
  2. 好きなもののリストを map() で表示する
  3. className を使ってスタイルを当てる(CSSは App.css に書く)
  4. 年齢が20歳以上なら「大人」、未満なら「未成年」と表示する

参考コード:

// src/App.jsx
function App() {
  const name = 'あなたの名前'
  const age = 25
  const hobbies = ['プログラミング', '読書', '料理']

  return (
    <div className="card">
      <h1 className="card-name">{name}</h1>
      <p className="card-age">
        年齢:{age}歳({age >= 20 ? '大人' : '未成年'}
      </p>
      <h2>趣味</h2>
      <ul className="hobby-list">
        {hobbies.map((hobby) => (
          <li key={hobby}>{hobby}</li>
        ))}
      </ul>
    </div>
  )
}

export default App

src/App.css に以下を追記してスタイルを整えてみましょう:

.card {
  max-width: 400px;
  margin: 2rem auto;
  padding: 2rem;
  border: 1px solid #ddd;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.card-name {
  font-size: 1.8rem;
  margin-bottom: 0.5rem;
}

.hobby-list {
  list-style: none;
  padding: 0;
}

.hobby-list li {
  padding: 0.3rem 0;
  border-bottom: 1px solid #eee;
}

完成したらこんな見た目になります:

localhost:5173
自己紹介カード。名前、年齢、趣味リストが表示されている
JSXで作った自己紹介カード

まとめ

このチャプターで学んだことをおさらいしましょう:

HTMLJSX
class=""className=""
for=""htmlFor=""
<input><input />
style="color: red"style={{ color: 'red' }}
<!-- コメント -->{/* コメント */}

JSXのポイントをまとめると:

次のチャプターでは、このJSXをコンポーネントという単位に分割して再利用可能にする方法を学びます。