【React】JSXとは何か?特徴や注意点を実例で解説(className, htmlFor, onClick, 変数・式・関数の呼び出し)

react-prograshi(プロぐらし)-kv React.js
記事内に広告が含まれていることがあります。

JavaScriptなのにHTMLが書かれている…これこそがReactの心臓部、「JSX」です。この一見変わった記法は、UIの構造とロジックを一つにまとめ、コードの可読性を飛躍的に高めてくれます。

しかし、見た目がHTMLに似ているがゆえに、「classが使えない」「複数の要素を並べられない」といった落とし穴も存在します。

本記事では、JSXとは何か?という根本的な問いに答えつつ、開発時に必ず必要となるclassName、htmlForの使い分けや、onClickでの関数呼び出しなど、注意すべきルールと実例を網羅的に解説しています。


JSXとは何か?

JSX は「JavaScript XML」の略で、JavaScriptファイルにHTML(っぽいもの)を書けるようにした拡張機能です。

見た目は HTMLやXML に似ていますが、ブラウザは直接理解できないためBabelやTypeScript のトランスパイラがJavaScriptに変換します。


JSXのファイル拡張子

JSXを使っているファイルでも、基本的には拡張子はそのまま.jsを使用します

ただし、Reactのプロジェクトでは、JSXが含まれていることをより明確にするため.jsxを使用することも一般的です。

拡張子説明
.js多くのReactプロジェクトで使われる標準的な拡張子です。JSXが書かれていても、ビルドツール(WebpackやViteなど)がJavaScriptとして処理します。
.jsxJSX構文が含まれているファイルであることを開発者に明示したい場合に使用されます。特にReactの初期の頃や、JavaScriptとJSXを明確に区別したいチームで採用されることがあります。
.tsxTypeScript(型定義付きJavaScript)を使うプロジェクトでは、拡張子に .tsx を使います。これはJSXとTypeScriptの両方が含まれていることを示します。


JSXとReactは別物

Reactを使うときにJSXも一緒に使うことがほとんどです。

ですが、JSXはReactの一部ではなく、全くの別物です。一緒に使われることが多いですが、片方だけを独立して使うことも可能です。

JSX とは言語の拡張であり、ReactはJavaScript ライブラリです。

補足

JSXはReactから独立して使用することも技術的には可能ですが、Reactのエコシステムで(Reactをより効率よく使うニーズに合わせて)開発されたため、ほとんどの場合、Reactと一緒に使われるものと認識して問題ありません。


JSXの特徴と注意点

HTMLよりもJSXの方が厳密なため、JSXを記述する上では注意しなければいけないポイントがあります。

JSXの特徴と注意点
  1. ルート要素は単一の親タグで囲む
  2. 中身のないフラグメントも使える
  3. 必ず閉じタグが必要
  4. classはclassName, forはhtmlFor
  5. キャメルケースで書く(スペースを使わずに大文字でつなぐ。例外あり)
  6. オブジェクトは二重波カッコで渡す


ルート要素は単一の親タグで囲む

JSXの中身は必ず単一の親タグで囲まれている必要があります

以下の場合、divで囲んであります。

<div>
  <h1>Hedy JSX</h1>
 <p>this is jsx</p>
  <ul>
    ...
  </ul>
</div>


最上位の階層に複数のタグがあるのはNGです。

  <h1>Hedy JSX</h1>
 <p>this is jsx</p>
  <ul>
    ...
  </ul>


中身のないフラグメントも使える

最上位の要素を単一の親タグで囲む際に、divを使いたくない場合は空のタグを使うことができます。

<>
  <h1>Hedy JSX</h1>
 <p>this is jsx</p>
  <ul>
    ...
  </ul>
</>

この、<></>をフラグメントと呼びます。

フラグメントを使えば、ブラウザの HTMLツリーに痕跡を残すことなく、複数の要素をまとめることができます。

JSXの親タグは単一でなければいけない理由

JSX は HTML のように見えますが、裏ではプレーンな JavaScript オブジェクトに変換されます

JavaScriptの関数は「1つの結果」しか返すことができません。これが、JSXで複数の要素を返せない根本的な理由です。

例えば、JavaScriptで以下のように2つの結果を返そうとするとエラーになります。

function createTwoObjects() {
  //エラー
  return
    { type: 'h1', children: 'Hello' };
    { type: 'button', children: 'Click' };
}

これを1つの値としてラップすることでエラーが発生せずに結果を返せるようになります。

function createTwoObjects() {
  //OK!配列という1つの「まとまり」を返しています
  return [
    { type: 'h1', children: 'Hello' },
    { type: 'button', children: 'Click' }
  ];
}


必ず閉じタグが必要

HTMLではimgタグやliタグなど閉じタグがなくても動作するものがあります。

ですが、JSXではそういったタグも必ず閉じタグをつける必要があります

<>
  <img 
    src="https://i.imgur.com/yXOvdOSs.jpg" 
    alt="Hedy Lamarr" 
    class="photo"
  >
  <br>
  <ul>
      <li>Invent new traffic lights
      <li>Rehearse a movie scene
      <li>Improve the spectrum technology
  </ul>
</>

 ↓ 必ず閉じタグをつけます。(つけないとエラーになります)

<>
  <img 
    src="https://i.imgur.com/yXOvdOSs.jpg" 
    alt="Hedy Lamarr" 
    class="photo"
  />
  <br></br>
  <ul>
      <li>Invent new traffic lights</li>
      <li>Rehearse a movie scene</li>
      <li>Improve the spectrum technology</li>
  </ul>
</>


classNameとhtmlFor

JavaScriptではclassとforは予約語で既に機能が決まっています。

このため、HTMLタグのclass属性とfor属性はJSXでは以下の指定された値で記述する必要があります。

  • className
  • htmlFor
// HTMLのclassではなく、classNameを使用
const element = <div className="greeting">Hello JSX!</div>;


キャメルケースで書く(スペースを使わずに大文字でつなぐ。例外あり)

属性名やイベント名、CSSプロパティ名はHTMLではすべて小文字ですが、JSXではJavaScriptのDOM APIに倣ってキャメルケースで記述します。


属性名の例

// input要素のtabindex属性は「tabIndex」にする
const input = <input type="text" tabIndex={0} />;


イベントハンドラの例

HTMLでの記述 (小文字)JSXでの記述 (キャメルケース)
onclick="handler()"onClick={handler}
onchange="handler()"onChange={handler}
onmouseover="handler()"onMouseOver={handler}
function handleClick() {
  console.log("クリックされました!");
}

// onclickではなく「onClick」を使用し、関数自体を渡す
const button = <button onClick={handleClick}>クリック</button>;


CSSのプロパティ名(style属性内で使用する場合)

CSSプロパティ名 (ケバブケース)JSXでの記述 (キャメルケース)
font-sizefontSize
background-colorbackgroundColor
border-radiusborderRadius

なお、スタイル属性のプロパティを渡す場合は2重波カッコで渡す必要があります。

✕NG: style=”font-size: 20px;” (文字列は無効)
〇OK: style={{ /* JavaScriptオブジェクト */ }}

以下のように、変数でオブジェクトを作って、それを波カッコの中に入れる記述もよく使われます。

const styles = {
  // 'font-size' ではなく 'fontSize'
  fontSize: '20px', 
  // 'background-color' ではなく 'backgroundColor'
  backgroundColor: 'lightblue'
};

// 中括弧を二重にしてオブジェクトを渡す
const styledElement = <p style={styles}>キャメルケースのスタイル</p>;



タグの中で変数や式、関数を呼び出す

JSXでは、タグの中で波カッコを使って変数や式、関数を呼び出すことができます。

▼変数の呼び出し

const name = '山田太郎';
const element = <h1>こんにちは、{name}さん!</h1>;


▼関数の呼び出し

function fullName(user) {
  return `${user.lastName} ${user.firstName}`;
}

const user = {
  firstName: '太郎',
  lastName: '佐藤'
};

//タグ内で関数を呼び出し、結果を埋め込む
const element = (
  <p>
    ユーザー名: {fullName(user)}
  </p>
);


属性の値を呼び出す際の注意点

タグ内の文字列の中で変数や式などを呼び出す場合は、波カッコと文字列をそのまま記述することができます。

const name = '山田太郎';
const element = <h1>こんにちは、{name}さん!</h1>;


ですが、属性の値など文字列となる場所で呼び出す場合は、文字列も波カッコの中に含める必要があります。


const baseUrl = 'https://i.imgur.com/';
const person = {
  name: 'Gregorio Y. Zara',
  imageId: '7vQD0fP',
  imageSize: 's',
};

export default function TodoList() {
  return (
      <img
        className="avatar"
        src={baseUrl + person.imageId + person.imageSize + ".jpg"}
        alt={person.name}
      </img>
  );
}

上記でsrcが以下のようになっていることがポイントです。

〇 src={baseUrl + person.imageId + person.imageSize + ".jpg"}

もしくはテンプレートリテラルで記述します。この場合も波カッコの中に全て含める必要があります。

〇 src={`${baseUrl}${person.imageId}${person.imageSize}.jpg`}


以下のように文字列の部分を外側に出すとエラーになります。

✕ src={baseUrl + person.imageId + person.imageSize}".jpg"


オブジェクトは二重波カッコで渡す

HTMLでは通常のオブジェクトも波カッコを使います。

ですが、JSXでは、JavaScriptの変数や式、関数などを実行するために波カッコを使います。

このため、JSXでオブジェクトをオブジェクトとして認識させるためには、二重波カッコでラップする必要があります。

例えば、JSX内で、コンポーネントにperson={ name: 'Lin Lanying', imageId: '1bX5QH6' }というオブジェクトを渡す場合は以下のように記述します。

export default function Profile() {
  return (
    <Avatar
      person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}
      size={100}
    />
  );
}


数値を呼び出すときは波カッコをつける

<img>タグのwidthheight属性は、HTMLでは通常width="100"のようにピクセル数を示す文字列として記述されます。

しかし、Reactでは、これらの属性に数値リテラル100)を渡すことを推奨しており、この場合、ブラウザはこれをピクセル値(100px)として解釈します。

  • width={100}: JavaScriptの数値 100 を渡している。
  • width="100": JavaScriptの文字列 "100" を渡している。

どちらでも動作しますが、width={100} のように波括弧を使うことで、その値が静的な文字列ではなく、プログラムが計算した値(ここでは数値リテラル)であることを明示し、将来的に変数の値を動的に渡す際にも一貫した記法を使えるようにしています。

function Avatar() {
  return (
    <img
      className="avatar"
      src="https://i.imgur.com/1bX5QH6.jpg"
      width={100}
      height={100}
    />
  );
}
数値リテラルとは何か?

リテラル(Literal)とは「文字通りの、額面通りの」という意味で、「コードに書いたものが、そのままその値である」という定数を表します。

つまり、数値リテラルとは変数に格納したり計算に使ったりするためにコード中に直接記述する、数字そのもののです。

const quantity = 100; // 100 は数値リテラル
let price = 19.99;    // 19.99 は数値リテラル

const total = quantity * price; // quantityとpriceは変数
const vat = total * 0.1;        // 0.1 は数値リテラル

数値リテラルの他にも、プログラミング言語には様々なリテラルが存在します。

リテラルの種類説明
文字列リテラル (String)"Hello"ダブルクォートまたはシングルクォートで囲まれた文字の並び。
真偽値リテラル (Boolean)truefalse真(正しい)か偽(間違っている)かを表す。
配列リテラル (Array)[1, 2, 3]角括弧で囲まれた要素の並び。
オブジェクトリテラル (Object){ name: "Taro" }波括弧で囲まれたキーと値のペア。



JSXコンバーター

元のHMTLをJSXに書き換えるのは面倒な場合があります。

そんなときに便利なHTML→JSXコンバーターもあります。

HTML to JSX
An online playground to convert HTML to JSX
タイトルとURLをコピーしました