ReactコンポーネントとJSXの基本
「コンポーネント」とは
Reactでは、画面の部品をコンポーネントとして定義します。
ざっくり言うと、「入力(props)を受け取って、JSX(見た目)を返すただの関数」です。
function Hello() {
return <h1>Hello, React!</h1>
}Helloがコンポーネント- 戻り値の
<h1>〜</h1>が JSX - 使う側は HTML タグのように
<Hello />と書く
App.jsx で使うと:
// App.jsx
function Hello() {
return <h1>Hello, React!</h1>
}
export default function App() {
return (
<div>
<Hello />
<p>Reactの世界へようこそ。</p>
</div>
)
}ポイント:
- コンポーネント名は 先頭を大文字 にする(Reactのルール)
<Hello />のように、自分で作ったコンポーネントをタグ風に書く
JSXの正体と基本ルール
JSX = JavaScriptの中でHTMLっぽく書ける記法 です。
コンパイル時に普通の React.createElement(...) 呼び出しに変換されます。
ルール1:戻り値は「1つの親要素」にまとめる
これは React 初心者がかなりの確率で引っかかるポイントです。
// NG:これはエラーになる
function Bad() {
return (
<h1>タイトル</h1>
<p>本文</p>
)
}JSXでは「隣り合う要素」はそのまま返せません。
必ず1つの親要素で包む必要があります。
function Good() {
return (
<div>
<h1>タイトル</h1>
<p>本文</p>
</div>
)
}または、<> </> で囲む(フラグメント)方法もよく使います。
function Good() {
return (
<>
<h1>タイトル</h1>
<p>本文</p>
</>
)
}ルール2:中括弧 {} の中にJS式を書ける
JSXの中では、中括弧 {} の中は JavaScript の世界です。
const name = 'Taro'
const count = 3
export default function App() {
return (
<div>
<h1>こんにちは、{name} さん</h1>
<p>カートの中身は {count} 個です</p>
<p>2 + 3 = {2 + 3}</p>
</div>
)
}{name}→ 変数展開{2 + 3}→ 式の結果を埋め込み{func()}→ 関数の戻り値を埋め込み、もOK
※ if 文はそのまま書けないので、三項演算子などを使います(これは後で解説します)
ルール3:HTMLと微妙に違う属性名
JSXではいくつかの属性名が普通のHTMLと違います。
代表的なもの:
class→classNamefor(labelの属性) →htmlFor
export default function App() {
return (
<div className="container">
<label htmlFor="name">名前</label>
<input id="name" type="text" />
</div>
)
}理由は、class や for が JavaScript の予約語と絡むのと、DOMのプロパティ名に合わせているためです。
ルール4:属性値にJSを渡すときも {}
文字列だけなら "..." でOKですが、変数や数値、関数を渡すときは {} を使います。
const title = 'ダッシュボード'
const size = 32
export default function App() {
return (
<header>
<h1 style={{ fontSize: size }}> {/* JSオブジェクトなので {{ }} になる */}
{title}
</h1>
<img src="/logo.png" alt="logo" />
</header>
)
}styleはオブジェクトなので{{ fontSize: size }}と二重波括弧になる(外側:JSXの{}, 内側:JSオブジェクトの{})src="/logo.png"はただの文字列なので{}はいらない
props:コンポーネントの「引数」
コンポーネントに値を渡したいときは、属性として書く ⇒ props で受け取る という形を取ります。
function Greeting(props) {
return <p>こんにちは、{props.name} さん!</p>
}
export default function App() {
return (
<div>
<Greeting name="太郎" />
<Greeting name="花子" />
</div>
)
}<Greeting name="太郎" />で、nameという属性を渡しているGreetingコンポーネントではprops.nameとして参照できる
よく使う書き方として 分割代入 があります:
function Greeting({ name }) {
return <p>こんにちは、{name} さん!</p>
}props オブジェクトから name プロパティだけ抜き出して受け取るイメージです。
複数のpropsを渡す例
function UserCard({ name, age, isActive }) {
return (
<div className="user-card">
<h2>{name}</h2>
<p>年齢: {age}</p>
<p>ステータス: {isActive ? 'アクティブ' : '休止中'}</p>
</div>
)
}
export default function App() {
return (
<>
<UserCard name="山田太郎" age={28} isActive={true} />
<UserCard name="佐藤花子" age={34} isActive={false} />
</>
)
}age={28}のように、数値や真偽値は{}で渡すisActive ? 'アクティブ' : '休止中'で三項演算子を使って表示を切り替え
コンポーネントの分割とファイル分け
規模が大きくなると、1ファイルに全部書くとすぐにカオスになります。
Reactでは、「1つのUIパーツ = 1コンポーネント = 1ファイル」くらいの粒度で分解していくのが基本です。
例:ユーザー一覧画面をざっくり構成すると
App.jsx… 全体のレイアウトUserList.jsx… ユーザーの一覧部分UserItem.jsx… 各ユーザー1件の表示
UserItem.jsx
// src/UserItem.jsx
export default function UserItem({ user }) {
return (
<li className="user-item">
<strong>{user.name}</strong>({user.email})
</li>
)
}UserList.jsx
// src/UserList.jsx
import UserItem from './UserItem'
export default function UserList({ users }) {
return (
<ul>
{users.map((u) => (
<UserItem key={u.id} user={u} />
))}
</ul>
)
}App.jsx
// src/App.jsx
import UserList from './UserList'
const dummyUsers = [
{ id: 1, name: '山田太郎', email: 'taro@example.com' },
{ id: 2, name: '佐藤花子', email: 'hanako@example.com' },
]
export default function App() {
return (
<div>
<h1>ユーザー一覧</h1>
<UserList users={dummyUsers} />
</div>
)
}ポイント:
- コンポーネントを細かく分けることで、
- ロジックの見通しがよくなる
- 再利用しやすくなる
- テストもしやすくなる
export defaultしたコンポーネントはimport X from '...'で読み込む
条件分岐
JSX 内でよく使うパターンを1つだけ先取りしておきます。
条件に応じて表示を変える
function StatusBadge({ isOnline }) {
return (
<span className={isOnline ? 'badge online' : 'badge offline'}>
{isOnline ? 'オンライン' : 'オフライン'}
</span>
)
}- クラス名もテキストも三項演算子で切り替え
- 「UIは状態の関数」という感覚に慣れていくのに良い練習です
まとめ
- コンポーネントは「入力⇒JSXを返す関数」
- JSXの基本ルール:
- 戻り値は1つの親要素で包む
{}でJS式を埋め込むclass→className,for→htmlFor
propsでコンポーネントにデータを渡し、再利用性の高いUIパーツを作っていく- ファイル分割しながら、小さい部品に分けていくのが基本
コメント