JSX とは
JavaScript の拡張であり、JavaScript ファイル内に HTML のようなマークアップを書けるようにするもの。ほとんどの React 開発者は JSX の簡潔さを好んでいるため、ほとんどのコードベースで JSX が使われている。
なぜ JSX なのか
長年にわたり、Web開発では、コンテンツは HTML で書き、デザインは CSS、ロジックは JavaScript とそれぞれ別ファイルにしていた。近年、Webアプリはよりインタラクティブなものを求められるようになり、JavaScript が HTML の部分を担当したい場面が出てきた。
JSX と React は別の物。一緒に使われることが多いが、JSX とは JavaScript の拡張であり、React は JavaScript ライブラリ。
JSX のルール
1. 単一のルート要素で囲む
JSX は複数の要素を並列に記述することはできない。複数の要素を記述したい場合、単一の親タグで囲む必要がある。例えば <div> タグ。余分な <div> を加えたくない場合、代わりに <> と </> を使うことができる。この中身のないタグはフラグメントと呼ばれるもの。フラグメントを使えば、ブラウザの HTML ツリーに痕跡を残すことなく、複数の要素をまとめることができる。
// エラーになる例
<div>Hello</div>
<div>World</div>
// 解決策1: divなどで囲う
<div>
<div>Hello</div>
<div>World</div>
</div>
// 解決策3: フラグメントを使う <> </>
<>
<div>Hello</div>
<div>World</div>
</>
2. すべてのタグを閉じる
JSX ではすべてのタグを明示的に閉じる必要がある。囲みタグはもちろんだが、<img> のような自動で閉じるタグは <img /> のように書かなければならない。
<div>
<br />
<img src="..." alt="" />
<input type="text" />
</div>
3. (ほぼ)すべてキャメルケースで!
JSX ではハイフンを含む名前や予約語(例:class)は使えない。React では多くの HTML および SVG の属性はキャメルケースで書かれる。例えば stroke-width の代わりに strokeWidth を使う。class は予約語なので、React では className を使う。
<img
src="..."
alt=""
className=""
/>
歴史的理由により、aria-* と data-* 属性は HTML 属性と同じようにハイフン付きで書くことになっている。
4. JavaScript 式は {} で囲む
JSX では JavaScript の式を埋め込むことができ、{}内に式を埋め込む。これにより、動的な値をJSX内に簡単に導入することができる。
const name = "Taro";
const greeting = <h1>Hello, {name}</h1>;
式を埋め込むことはできるが、文を埋め込むことはできない。例えば、if 文や、for 文など。誤解を恐れずに言うと、右辺におけるようなものを埋め込むことができる。
JSX の正体
JSX は JavaScript の一部ではないため、ブラウザで直接実行することはできない。そのため、Babel や TypeScript などのトランスパイラを使って JavaScript に変換してから使う。
const HelloWorld = () => <h1>Hello world</h1>;
const HelloWorld = () => React.createElement("h1", null, "Hello world");
この結果からわかる通り、JSX の正体は React.createElement() が返すただのオブジェクト。そして、返されるオブジェクトを React要素 と呼ぶ。
ベストプラクティス
マルチラインの JSX はカッコで囲む
複数行に渡る JSX は可読性を上げるためにカッコで囲むことが推奨される。
// Good
const Good = () => {
return (
<div>
<h1>Hello, world!</h1>
</div>
);
};
// Bad
const Bad = () => {
return <div>
<h1>Hello, world!</h1>
</div>;
};
自己終了タグを利用する
JSXでは、内容が空の要素は開始タグと終了タグを省略して、自己終了タグとして書ける。
// 長いバージョン
const a = <input></input>;
// 短いバージョン(自己終了タグ)
const b = <input />;
true の場合は真偽属性を省略する
属性の値が true の場合、その属性名だけ記述することで属性の値を省略することが可能。この書き方を真偽属性と呼ぶ。
// 長いバージョン
const a = <input required={true} />;
// 短いバージョン(真偽属性)
const b = <input required />;
マップ関数内で一意の key プロパティを使用する
map() 関数を使用してリストを作成する場合、各要素に一意の key プロパティを付与することが推奨される。これにより React は変更、追加、削除を効率的に適用できる。
const listItems = numbers.map((number) => (
<li key={number.toString()}>{number}</li>
));
参考