
Reactで使用するJSX記法。本記事では、JSXのメリット・デメリットをわかりやすく解説し、使い方のポイントを紹介します。
通常のJavaScriptで書くときとの違いを理解できるようにまとめましたので是非ご参照ください。
JSXとは何か
JSX(JavaScript XML)とは、JavaScriptの拡張構文であり、JavaScriptファイル内にHTMLのような構文を記述できるもので、JSX記法はその記述方法のことになります。
基本的な構文
const element = (
<>
<h1>Hello</h1>
<p>World</p>
</>
);
基本的にJavaScriptファイル内にHTMLを記述するような書き方になります。
記述方法はHTMLとは厳密には異なり、JSX記法のルールに基づいて記述します。詳しくはReactの公式ドキュメントサイトをご参照ください。
メリットとデメリット
メリット
本題に入りますが、結論、JSXのメリットは「可読性」にあります。
先ほどの構文を見てもわかる通り、HTMLのような構造で記述できるので、直感的に理解しやすいです。「何を表示しようとしているのかがパッと見てわかる」と言う点で優れています。
通常の JavaScript で React.createElement を使うと以下のように書きます。
const element = React.createElement(
'div',
'null',
React.createElement('h1', null, 'Hello'),
React.createElement('p', null, 'World')
);
このようにネストが多くなりわかりづらくなります。
コンポーネントを用いて再利用可能なパーツに分けたい時には、より可読性の高さが伺えます。
例として、ボタンをコンポーネント化して表示させるコードを確認してみましょう。
まずはJSX記法を用いずにコンポーネント化した例です。
function MyButton(props) {
return React.createElement(
'button',
{
onClick: props.onClick,
style: { color: 'white', backgroundColor: 'green' },
},
props.label
);
}
function App() {
return React.createElement(
'div',
null,
React.createElement(MyButton, { label: 'OK', onClick: () => alert('OK') }),
React.createElement(MyButton, { label: 'Cancel', onClick: () => alert('Cancel') })
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(React.createElement(App));
同じくネストされた構造でわかりづらいです。
これをJSX記法では以下のように記述することができます。
function MyButton({label, onClick}) {
return (
<button onClick={onClick} style={{ color:'White', backgroundColor:'green'}}>
{label}
</button>
);
}
function App() {
return (
<div>
<MyButton label="OK" onClick={() => alert('OK')} />
<MyButton label="Cancel" onClick={() => alert('Cancel')} />
</div>
);
}
propsの受け渡しも自然に見えますね。
ついでにリスト表示を作成したい場合も確認してみましょう。
まずはJSX記法を用いずにリスト表示する例です。
const items = [
{ id: 'a1', name: 'Apple' },
{ id: 'b2', name: 'Banana' },
{ id: 'c3', name: 'Cherry' },
];
const list = React.createElement(
'ul',
null,
items.map((item) =>
React.createElement(
'li',
{ key: item.id },
React.createElement(
'div',
null,
React.createElement('label', null, item.name),
React.createElement(
'button',
{ onClick: () => alert(item.name) },
'Click'
)
)
)
)
);
こちらもReact.createElementが何重にもネストしていて見通しが悪いです。
JSX記法で書いてみます。
const items = [
{ id: 'a1', name: 'Apple' },
{ id: 'b2', name: 'Banana' },
{ id: 'c3', name: 'Cherry' },
];
const list = (
<ul>
{items.map((item) => (
<li key={item.id}>
<div>
<label>{item.name}</label>
<button onClick={() => alert(item.name)}>Click</button>
</div>
</li>
))}
</ul>
);
要素の入れ子がありますが、インデントとタグで構造を把握しやすくなりました。このように、ネスト構造が増えるほどJSX記法の可読性が相対的に高くなることがわかります。
デメリット
JSX記法のデメリットは、「複雑なロジック(条件分岐やループ)が入り込んでくると読みにくくなることがある」ということです。
具体例とその対処法を説明します。
[悪い例①]
複雑な条件分岐が中括弧{}の中にネストされているコードです。
return (
<div>
{ isLoggedIn ? (
user.isAdmin ? (
<p>管理者としてログイン中</p>
) : (
<p>ユーザーとしてログイン中</P>
)
) : (
<p>ログインしてください</p>
)}
</div>
);
読みづらく、条件がさらに増えると保守が困難になりやすいです。
対処法としては、JSXの中に複雑なロジックを書かず、事前に変数で分岐を整理してからJSXに渡します。
let message;
if (!isLoggedIn) {
message = <p>ログインしてください。</p>;
} else if (user.isAdmin) {
message = <p>管理者としてログイン中です。</p>;
} else {
message = <p>ユーザーとしてログイン中です。</p>;
}
return <div>{message}</div>;
[悪い例2]
こちらもJSX内に計算ロジックが埋め込まれています。
{items.map((item, index) => (
<li key={index}>
{item.name}:{item.value * 2 + 10} です。
</li>
))}
計算がもっと複雑になった場合、何を表示しているのかが読みづらくなる恐れがあります。
また、map()の中で無名関数を使って直接JSXを返しているのも問題点です。
対処法としては、ロジックを外で変数として計算します。
{items.map((item) => {
const displayValue = item.value * 2 + 10;
return (
<li key={item.id}>
{item.name}:{displayValue} です。
</li>
);
})}
少し冗長になりますが、読みやすくなりました。拡張性はこちらの方が高いので、条件や処理を増やしやすくなります。どちらを使うかは「表示内容の複雑さ」や「今後の拡張性」を踏まえて選ぶと良いです。
まとめ
- JSX(JavaScript XML)とは、JavaScriptの拡張構文であり、JavaScriptファイル内にHTMLのような構文を記述できるもので、JSX記法はその記述方法のことです。
- JSXは単純なUI構造では直感的で可読性を高めますが、複雑なロジックの処理やコード構造をきれいに保つことまでは保証してくれません。
- したがって、JSXと通常のJSを使い分けて、可読性・保守性の高いコードを書くように努めなければなりません。
コメント