React基礎講座 #3 JSXとは何か?
前回はViteで初めてのReactプロジェクトを作って開発サーバーを立ち上げました。その過程で私たちは自然と次のようなコードを見ました。
function App() {
return (
<div>
<h1>こんにちは、React!</h1>
</div>
);
}関数の中でHTMLのようなコードをそのままreturnしています。JavaScriptの中にHTMLだなんて、どこか違和感がありませんか?今回はこの不思議な構文であるJSXが何で、どう使うのかを見ていきましょう。
JSXとは何か? #
JSX(JavaScript XML) はJavaScriptにHTMLに似たマークアップ構文を組み合わせたものです。JavaScriptの公式構文ではありませんが、FacebookがReactを発表したときに一緒に提案した拡張構文であり、今日ではほぼすべてのReactプロジェクトがJSXを使っています。
実はJSXなしでもReactコードを書くことはできます。次の2つのコードはまったく同じ結果を作ります。
function App() {
return <h1>Hello</h1>;
}function App() {
return React.createElement('h1', null, 'Hello');
}上の方がはるかに読みやすいことには誰もが同意するはずです。だから私たちはJSXを使います。
ブラウザはJSXを知らない #
ブラウザのJavaScriptエンジンはJSXを直接理解できません。私たちがJSXで書いたコードはビルド過程で通常のJavaScriptに変換された後、ブラウザに渡されます。前回使ったViteのようなビルドツールがこの変換を自動で処理してくれるので、私たちは気にせずJSXを思う存分使うことができます。
JSXの基本ルール #
JSXはHTMLに似て見えますが、いくつか異なるルールがあります。初めて学ぶ方々がもっとも混乱する部分なので、順を追って見ていきます。
ルール1. 必ず1つの親要素で包まなければならない #
JSXは結局、関数が何かをreturnするものなので、一度に1つの値しか返せません。したがって、複数の要素を一度に返すには必ず1つの親で包まなければなりません。
function App() {
return (
<h1>こんにちは</h1>
<p>今日も楽しい1日をお過ごしください</p>
);
}function App() {
return (
<div>
<h1>こんにちは</h1>
<p>今日も楽しい1日をお過ごしください</p>
</div>
);
}<div>で包めばよいのですが、意味のない<div>が増えるのが気に入らないときがあります。そんなときは空のタグであるFragmentを使えます。
function App() {
return (
<>
<h1>こんにちは</h1>
<p>今日も楽しい1日をお過ごしください</p>
</>
);
}<>...</>はReact.Fragmentの短縮表記で、実際のDOMにはどんな要素も作らず、複数の子をまとめる役割をします。
ルール2. すべてのタグは閉じなければならない #
HTMLでは<img>、<br>、<input>のような一部のタグを閉じずに使ってもよかったです。しかしJSXではすべてのタグを閉じなければなりません。子のないタグは末尾に/を付けて自己閉じ(self-closing)で処理します。
<img src="/cat.png" alt="猫" />
<br />
<input type="text" />ルール3. classの代わりにclassName
#
HTMLでCSSクラスを指定するときに使ったclass属性はJavaScriptの予約語と重なるため、JSXではclassNameを使います。
<div className="card">カードです</div>同じ理由で<label>のfor属性もhtmlForに変わります。
<label htmlFor="email">メール</label>
<input id="email" type="email" />ルール4. 属性名はcamelCase #
HTMLでは属性名がすべて小文字でしたが(onclick、tabindex、readonly)、JSXではcamelCaseを使います。
<button onClick={handleClick} tabIndex={0}>クリック</button>
<input readOnly value="固定値" />JSXの中にJavaScriptの式を入れる #
JSXの本当の力は、マークアップの中にJavaScriptの式を自由に挟み込めることにあります。波括弧{ }の中に入るすべてのJavaScriptの式は評価されて、その結果が画面に出力されます。
function App() {
const name = 'チョルス';
const age = 30;
return (
<div>
<h1>こんにちは、{name}さん!</h1>
<p>年齢: {age}歳</p>
<p>10年後には: {age + 10}歳</p>
</div>
);
}関数呼び出しも、三項演算子も、配列のメソッドも、すべて式であれば使えます。
function App() {
const isLoggedIn = true;
const items = ['りんご', 'バナナ', 'チェリー'];
return (
<div>
<h1>{isLoggedIn ? 'ようこそ!' : 'ログインしてください'}</h1>
<ul>
{items.map(item => <li key={item}>{item}</li>)}
</ul>
</div>
);
}if文やforループのような文(statement) は直接入れられません。条件付き出力が必要なら三項演算子や&&演算子を、繰り返し出力が必要ならmapメソッドを使う形です。詳しい内容は#7 条件付きレンダリングと#8 リストとkeyで扱います。インラインスタイル #
JSXで直接スタイルを指定するにはオブジェクト形式で渡します。CSSプロパティ名も同様にcamelCaseです。
function App() {
return (
<h1 style={{ color: 'tomato', fontSize: '32px' }}>
スタイルが適用されたタイトル
</h1>
);
}波括弧が2つあるのは最初は違和感を覚えるかもしれませんが、外側の{ }は「JSX内のJavaScriptの式」を意味し、内側の{ }は「JavaScriptのオブジェクトリテラル」だからです。
JSX内のコメント #
JSX内でコメントを書くにはJavaScriptの式なので波括弧で包まなければなりません。
function App() {
return (
<div>
{/* これはJSXコメントです */}
<h1>タイトル</h1>
</div>
);
}自分でやってみる #
前回作ったプロジェクトのsrc/App.jsxを次のように変えてみてください。
function App() {
const name = 'チョルス';
const fruits = ['りんご', 'バナナ', 'チェリー'];
return (
<>
<h1>こんにちは、{name}さん!</h1>
<p>今日の果物は全部で{fruits.length}個です:</p>
<ul>
{fruits.map(fruit => <li key={fruit}>{fruit}</li>)}
</ul>
</>
);
}
export default App;保存するとHMRですぐに画面が更新されるでしょう。変数の値を変えたり、配列に新しい果物を追加してみたりしながら、画面がどう反応するか直接確認してみてください。
おわりに #
今回の記事ではReactの核心構文であるJSXを紹介し、基本ルール4つ(親要素で包む、タグを閉じる、className/htmlFor、camelCase属性)、JSの式の埋め込み、インラインスタイル、コメントを見てきました。これでJSXコードを見たときの違和感がだいぶ減ったことを願います。
次の記事「React基礎講座 #4 コンポーネントとprops」では、画面を小さな単位に分ける核心概念であるコンポーネントと、コンポーネントにデータを渡す通路であるpropsを扱ってみることにしましょう。