JSXを使ったマークアップ

JSX は、JavaScriptの構文拡張で、JavaScriptファイル内にHTMLのようなマークアップを記述することができます。コンポーネントを記述する方法は他にもありますが、ほとんどのReact開発者はJSXの簡潔さを好み、ほとんどのコードベースでJSXが使用されています。

学習内容

  • Reactがマークアップとレンダリングロジックを混在させる理由
  • JSXとHTMLの違い
  • JSXで情報を表示する方法

JSX:マークアップをJavaScriptに埋め込む

WebはHTML、CSS、JavaScriptで構築されてきました。長年、Web開発者はコンテンツをHTMLに、デザインをCSSに、ロジックをJavaScriptに(多くの場合、別々のファイルに)分けてきました。コンテンツはHTML内でマークアップされ、ページのロジックはJavaScript内で別々に存在していました。

HTML markup with purple background and a div with two child tags: p and form.
HTML markup with purple background and a div with two child tags: p and form.

HTML

Three JavaScript handlers with yellow background: onSubmit, onLogin, and onClick.
Three JavaScript handlers with yellow background: onSubmit, onLogin, and onClick.

JavaScript

しかし、Webがよりインタラクティブになるにつれて、ロジックがコンテンツを決定することが多くなりました。JavaScriptがHTMLを制御するようになったのです。そのため、Reactでは、レンダリングロジックとマークアップがコンポーネントという同じ場所に一緒に存在します。

React component with HTML and JavaScript from previous examples mixed. Function name is Sidebar which calls the function isLoggedIn, highlighted in yellow. Nested inside the function highlighted in purple is the p tag from before, and a Form tag referencing the component shown in the next diagram.
React component with HTML and JavaScript from previous examples mixed. Function name is Sidebar which calls the function isLoggedIn, highlighted in yellow. Nested inside the function highlighted in purple is the p tag from before, and a Form tag referencing the component shown in the next diagram.

Sidebar.js Reactコンポーネント

React component with HTML and JavaScript from previous examples mixed. Function name is Form containing two handlers onClick and onSubmit highlighted in yellow. Following the handlers is HTML highlighted in purple. The HTML contains a form element with a nested input element, each with an onClick prop.
React component with HTML and JavaScript from previous examples mixed. Function name is Form containing two handlers onClick and onSubmit highlighted in yellow. Following the handlers is HTML highlighted in purple. The HTML contains a form element with a nested input element, each with an onClick prop.

Form.js Reactコンポーネント

ボタンのレンダリングロジックとマークアップを一緒にすることで、編集のたびに互いに同期した状態を保つことができます。逆に、ボタンのマークアップとサイドバーのマークアップのように、無関係な詳細は互いに分離されているため、どちらかを単独で変更しても安全です。

各Reactコンポーネントは、Reactがブラウザにレンダリングするマークアップを含むことができるJavaScript関数です。Reactコンポーネントは、JSXと呼ばれる構文拡張を使用して、そのマークアップを表します。JSXはHTMLによく似ていますが、少し厳格で、動的な情報を表示することができます。これを理解する最良の方法は、HTMLマークアップをJSXマークアップに変換することです。

注記

JSXとReactは別物です。これらはしばしば一緒に使用されますが、互いに独立して使用することもできます。JSXは構文拡張であり、ReactはJavaScriptライブラリです。

HTMLからJSXへの変換

有効なHTMLがあるとします。

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

これをコンポーネントに配置したいとします。

export default function TodoList() {
return (
// ???
)
}

そのままコピーして貼り付けても、機能しません。

export default function TodoList() {
  return (
    // This doesn't quite work!
    <h1>Hedy Lamarr's Todos</h1>
    <img 
      src="https://i.imgur.com/yXOvdOSs.jpg" 
      alt="Hedy Lamarr" 
      class="photo"
    >
    <ul>
      <li>Invent new traffic lights
      <li>Rehearse a movie scene
      <li>Improve the spectrum technology
    </ul>

これは、JSXの方が厳格で、HTMLよりもルールがいくつか多いからです。上記のエラーメッセージを読めば、マークアップを修正する方法がわかります。または、以下のガイドに従ってください。

注記

ほとんどの場合、Reactの画面上のエラーメッセージは、問題の場所を見つけるのに役立ちます。行き詰まったら、それらを読んでみてください。

JSXのルール

1. 単一のルート要素を返す

コンポーネントから複数の要素を返すには、単一の親タグで囲みます。

たとえば、<div>を使用できます。

<div>
<h1>Hedy Lamarr's Todos</h1>
<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
class="photo"
>
<ul>
...
</ul>
</div>

マークアップに余分な <div> を追加したくない場合は、代わりに <></> を記述できます。

<>
<h1>Hedy Lamarr's Todos</h1>
<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
class="photo"
>
<ul>
...
</ul>
</>

この空のタグは、フラグメント と呼ばれます。フラグメントを使用すると、ブラウザのHTMLツリーに何も痕跡を残さずに要素をグループ化できます。

詳細解説

なぜ複数のJSXタグをラップする必要があるのですか? (リンクアイコン)

JSXはHTMLのように見えますが、内部的にはプレーンなJavaScriptオブジェクトに変換されます。配列でラップせずに、関数から2つのオブジェクトを返すことはできません。これは、別のタグまたはフラグメントでラップせずに2つのJSXタグを返すことができない理由でもあります。

2. すべてのタグを閉じる (リンクアイコン)

JSXでは、タグを明示的に閉じる必要があります。 <img> のような自己終了タグは <img /> になり、 <li>oranges のようなラップタグは <li>oranges</li> と記述する必要があります。

ヘディ・ラマーの画像とリスト項目は、このように閉じられています。

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

3. すべて ほとんどのものをキャメルケースにする! (リンクアイコン)

JSXはJavaScriptに変換され、JSXで記述された属性はJavaScriptオブジェクトのキーになります。独自のコンポーネントでは、多くの場合、これらの属性を変数に読み込みたいと思うでしょう。ただし、JavaScriptには変数名に制限があります。たとえば、変数名にダッシュを含めたり、 class のような予約語を使用したりすることはできません。

このため、Reactでは、多くのHTMLおよびSVG属性はキャメルケースで記述されます。たとえば、 stroke-width の代わりに strokeWidth を使用します。 class は予約語であるため、Reactでは、対応するDOMプロパティ にちなんで、代わりに className と記述します。

<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
className="photo"
/>

DOMコンポーネントのプロップのリストで、これらの属性をすべて見つけることができます。 間違えた場合でも、心配しないでください。Reactはブラウザコンソールに、考えられる修正を含むメッセージを出力します。

落とし穴

歴史的な理由から、aria-* 属性と data-* 属性は、HTMLと同様にダッシュを使用して記述されます。

プロのヒント:JSXコンバーターを使用する (リンクアイコン)

既存のマークアップでこれらの属性をすべて変換するのは面倒な場合があります!既存のHTMLおよびSVGをJSXに変換するには、コンバーター を使用することをお勧めします。コンバーターは実際には非常に便利ですが、JSXを自分で快適に記述できるように、何が起こっているのかを理解しておく価値はあります。

最終結果はこちらです

export default function TodoList() {
  return (
    <>
      <h1>Hedy Lamarr's Todos</h1>
      <img 
        src="https://i.imgur.com/yXOvdOSs.jpg" 
        alt="Hedy Lamarr" 
        className="photo" 
      />
      <ul>
        <li>Invent new traffic lights</li>
        <li>Rehearse a movie scene</li>
        <li>Improve the spectrum technology</li>
      </ul>
    </>
  );
}

まとめ (リンクアイコン)

JSXが存在する理由と、コンポーネントでJSXを使用する方法がわかりました。

  • Reactコンポーネントは、レンダリングロジックとマークアップを関連付けているため、まとめてグループ化します。
  • JSXはHTMLに似ていますが、いくつかの違いがあります。必要に応じて、コンバーター を使用できます。
  • エラーメッセージは、多くの場合、マークアップを修正するための正しい方向を示しています。

チャレンジ 1(of以下は文脈がないため翻訳できません) 1:
HTMLをJSXに変換する

このHTMLはコンポーネントに貼り付けられましたが、有効なJSXではありません。修正してください。

export default function Bio() {
  return (
    <div class="intro">
      <h1>Welcome to my website!</h1>
    </div>
    <p class="summary">
      You can find my thoughts here.
      <br><br>
      <b>And <i>pictures</b></i> of scientists!
    </p>
  );
}

手動で行うか、コンバーターを使用するかはあなた次第です!