Component
| 対応: | React 16.8(2019) |
|---|
『React』のコンポーネントは、UIを独立した部品として定義し再利用するための仕組みです。アプリケーションの画面を小さな部品に分割し、それぞれを組み合わせて複雑なUIを構築できます。
構文
// 関数コンポーネントの基本構文
function コンポーネント名(props) {
return (
<JSX>レンダリングする内容</JSX>
);
}
// アロー関数を使った書き方
const コンポーネント名 = (props) => {
return (
<JSX>レンダリングする内容</JSX>
);
};
// プロパティを分割代入で受け取る書き方
function コンポーネント名({ プロパティ名1, プロパティ名2 }) {
return (
<JSX>レンダリングする内容</JSX>
);
}
コンポーネントの種類一覧
| 種類 | 概要 |
|---|---|
| 関数コンポーネント | JavaScript の関数として定義するコンポーネントです。現在の React 開発で推奨される標準的な書き方です。 |
| クラスコンポーネント | ES6 クラス構文を使って定義するコンポーネントです。React 16.8 以前はこちらが主流でしたが、現在は関数コンポーネントへの移行が推奨されています。 |
| ルートコンポーネント | アプリケーションの最上位に配置されるコンポーネントです。慣例的に『App』という名前が使われます。 |
| 子コンポーネント | 別のコンポーネントの内部で使用されるコンポーネントです。親から『props』でデータを受け取ります。 |
props の主なルール一覧
| ルール | 概要 |
|---|---|
| 読み取り専用 | コンポーネントは受け取った『props』を直接変更してはいけません。データは常に親から子へ一方向に流れます。 |
| 任意の型を渡せる | 文字列・数値・真偽値・配列・オブジェクト・関数など、JavaScript のあらゆる値を『props』として渡せます。 |
| デフォルト値の設定 | 『defaultProps』またはデフォルト引数を使って、省略時の初期値を設定できます。 |
| children | コンポーネントタグの開始タグと終了タグの間に記述した内容は、『props.children』として受け取れます。 |
サンプルコード
挨拶を表示するコンポーネントを定義し、複数箇所で再利用する例です。
// Greeting コンポーネントの定義
// name プロパティで挨拶する相手の名前を受け取ります
function Greeting({ name, lang }) {
// lang プロパティに応じて挨拶文を切り替えます
var message = lang === 'en' ? 'Hello, ' : 'こんにちは、';
return (
<p>{message}{name}さん!</p>
);
}
// Card コンポーネントの定義
// children を使って任意の内容をラップできます
function Card({ title, children }) {
return (
<div className="card">
<h2>{title}</h2>
{/* children には親から渡された JSX がそのまま入ります */}
{children}
</div>
);
}
// App コンポーネント(ルートコンポーネント)
// Greeting と Card を組み合わせて画面を構成します
function App() {
return (
<div>
{/* Greeting コンポーネントを異なる props で再利用しています */}
<Greeting name="虎杖悠仁" lang="ja" />
<Greeting name="Yuji" lang="en" />
{/* Card コンポーネントで Greeting を囲んでいます */}
<Card title="メンバー紹介">
<Greeting name="五条悟" lang="ja" />
<Greeting name="伏黒恵" lang="ja" />
</Card>
</div>
);
}
export default App;
概要
コンポーネントは『React』アプリケーションの基本的な構成単位です。関数として定義し、JSX を返すだけでコンポーネントを作成できます。コンポーネント名は必ず大文字で始める必要があります(小文字で始まる名前は HTML タグとして解釈されます)。
親コンポーネントから子コンポーネントへのデータの受け渡しには『props』を使います。『props』は読み取り専用であり、子コンポーネントが直接変更することはできません。コンポーネント内部で変化するデータを扱う場合は、『useState()』などのフックを使用します。
コンポーネントを小さく分割して再利用することで、コードの保守性と可読性が向上します。ボタンやカードのような汎用的なUI部品から、フォームやモーダルのような複雑な機能まで、あらゆる粒度でコンポーネントとして定義できます。
よくあるミス
コンポーネント名を小文字で始めると HTML 要素として扱われる
React はコンポーネント名の先頭が小文字の場合、HTML のカスタム要素として解釈します。function myGreeting(){} のように定義して <myGreeting /> と書いても React コンポーネントとしてレンダリングされません。コンポーネント名は必ず大文字で始めます。
greeting_ng.jsx
// 小文字始まりのため React コンポーネントとして認識されません
function greeting({ name }) {
return <p>こんにちは、{name}さん!</p>;
}
function App() {
// <greeting> は HTML 要素として解釈され、期待通りに動作しません
return <greeting name="虎杖悠仁" />;
}
修正後:
greeting_ok.jsx
// 大文字始まりにすることで React コンポーネントとして認識されます
function Greeting({ name }) {
return <p>こんにちは、{name}さん!</p>;
}
function App() {
return <Greeting name="虎杖悠仁" />;
}
return で複数の要素を返すと構文エラー
JSX では return に複数のルート要素を並べると構文エラーになります。Fragment(<>〜</>)または React.Fragment で囲んで単一のルートにします。
multi_root_ng.jsx
function MemberList() {
// ルート要素が複数あるため構文エラーになります
return (
<h2>呪術師一覧</h2>
<ul>
<li>虎杖悠仁</li>
<li>五条悟</li>
</ul>
);
}
修正後:
multi_root_ok.jsx
function MemberList() {
// Fragment で囲むと余分な DOM 要素を追加せずに複数要素を返せます
return (
<>
<h2>呪術師一覧</h2>
<ul>
<li>虎杖悠仁</li>
<li>五条悟</li>
</ul>
>
);
}
コンポーネントを条件分岐の中で定義してしまう
コンポーネントを if やループの中で定義すると、レンダリングのたびに新しいコンポーネント型が生成されます。React は型が変わったと判断して毎回アンマウント→マウントを繰り返し、パフォーマンスと state の保持に問題が生じます。コンポーネントは必ずモジュールのトップレベルで定義します。
inline_component_ng.jsx
function App({ isLoggedIn }) {
// 条件分岐の中でコンポーネントを定義しています
// レンダリングのたびに新しい型になり再マウントが繰り返されます
if (isLoggedIn) {
function Profile() {
return <p>五条悟 - 特級術師</p>;
}
return <Profile />;
}
return <p>ログインしてください</p>;
}
修正後:
inline_component_ok.jsx
// コンポーネントはモジュールのトップレベルで定義します
function Profile() {
return <p>五条悟 - 特級術師</p>;
}
function App({ isLoggedIn }) {
// 定義済みのコンポーネントを条件に応じて使い分けます
if (isLoggedIn) {
return <Profile />;
}
return <p>ログインしてください</p>;
}
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。