JSX とコンポーネント
関数コンポーネント
React コンポーネントは JSX を返す JavaScript 関数です。コンポーネント名は大文字で始める必要があります(小文字 = HTML タグ)。Props は属性として渡されパラメータで分割代入されます。JSX は React.createElement() の糖衣構文です。常に単一のルート要素を返します(または Fragment を使用)。コンポーネントは純粋でなければなりません — 同じ props = 同じ出力。
// Basic function component
function Welcome({ name }) {
return <h1>Hello, {name}!</h1>;
}
// Arrow function component
const Greeting = ({ name = 'Guest' }) => (
<p>Welcome, {name}!</p>
);
// Composing components
function App() {
return (
<div>
<Welcome name="Alice" />
<Welcome name="Bob" />
<Greeting />
</div>
);
}JSX 式
JSX は中括弧 {} で JavaScript 式を埋め込むことを許可します。変数、関数呼び出し、三項演算子、値を返す任意の式を配置できます。文(if、for、switch)は直接許可されません — 三項または IIFE を使用してください。ブール値(true、false)、null、undefined は何もレンダリングしません。数値と文字列はテキストとしてレンダリングされます。オブジェクトは有効な React 子ではありません。
function Expression({ user, items }) {
const fullName = user.first + ' ' + user.last;
const itemCount = items.length;
return (
<div>
{/* Expressions in curly braces */}
<h1>{fullName}</h1>
<p>{itemCount} items</p>
{/* Conditional */}
<p>{itemCount > 0 ? 'In stock' : 'Sold out'}</p>
{/* Method calls */}
<p>{fullName.toUpperCase()}</p>
{/* Numbers and booleans render as nothing */}
<p>{false}{null}{undefined}</p>
</div>
);
}Fragment と JSX 内のリスト
Fragment(<>...</>)は余分な DOM ノードを追加せずに複数要素をグループ化します — <div> で囲むよりクリーンです。key を渡す必要がある場合は <Fragment key={...}> を使用します。JSX 要素の配列には一意の key props が必要です。静的リストでは配列インデックスを key として機能しますが、動的リストではレンダリングバグを防ぐため安定した ID を使用してください。Fragment は不要なラッパー要素を減らすことでパフォーマンスを向上させます。
// Fragment: group without extra DOM node
function App() {
return (
<>
<header>Header</header>
<main>Content</main>
<footer>Footer</footer>
</>
);
}
// Array of elements (needs keys)
function List() {
const fruits = ['Apple', 'Banana', 'Cherry'];
return (
<ul>
{fruits.map((fruit, i) => (
<li key={i}>{fruit}</li>
))}
</ul>
);
}条件付きレンダリング
React は複数の条件付きレンダリングパターンを提供します。if/else ロジックには早期リターン。どちらかには三項(cond ? A : B)。表示/非表示には論理 AND(cond && <Component/>)。複雑な分岐には IIFE。JSX に複雑なロジックを埋め込むのを避け — 変数やヘルパー関数に抽出してください。switch 文にはルックアップオブジェクトや別の関数への抽出を使用します。偽値(0、'')はレンダリングされるため、数値には && ではなく三項を使用してください。
function Greeting({ isLoggedIn, user }) {
// 1. If/else (use early return)
if (!isLoggedIn) return <Login />;
// 2. Ternary operator
return (
<div>
{user ? <Dashboard user={user} /> : <Loading />}
{/* 3. Logical AND (render if truthy) */}
{user.isAdmin && <AdminPanel />}
{/* 4. IIFE for complex logic */}
{(() => {
if (user.role === 'admin') return <Admin />;
if (user.role === 'mod') return <Mod />;
return <User />;
})()}
</div>
);
}Children と Render Props
children prop は開始タグと終了タグ間の要素を含みます — コンポーザブルコンポーネント(カード、モーダル、レイアウト)に不可欠。Render props はデータを受け取り JSX を返す関数を prop として渡します — ロジック共有の HOC やフックの代替。Render props はフックでは一般的ではありませんが、コンポーネント注入パターンにはまだ有用です。children は明示的に渡す必要のない特別な prop です。
// children prop: content between tags
function Card({ title, children }) {
return (
<div className="card">
<h2>{title}</h2>
<div className="card-body">{children}</div>
</div>
);
}
// Usage
<Card title="Profile">
<p>Name: Alice</p>
<p>Age: 30</p>
</Card>
// Render prop pattern
function DataProvider({ render }) {
const data = fetchData();
return <div>{render(data)}</div>;
}Props
Props の受け渡し
Props は親から子に渡される読み取り専用データです。任意の JavaScript 値にできます:文字列、数値、ブール値、配列、オブジェクト、関数。文字列値は引用符を使用し(name='Alice')、他のすべての値は中括弧を使用します(age={30})。関数を props にすることで子から親への通信(コールバック)が可能です。Props は下方向に流れます — 子は props を変更できません 。双方向データバインディングには、共通の親に状態をリフトします。
// Parent passes props to child
function App() {
return (
<User
name="Alice"
age={30}
isActive={true}
tags={['admin', 'dev']}
onClick={() => console.log('clicked')}
/>
);
}
// Child receives props
function User({ name, age, isActive, tags, onClick }) {
return (
<div onClick={onClick}>
<h1>{name}</h1>
<p>Age: {age}</p>
<p>Status: {isActive ? 'Active' : 'Inactive'}</p>
</div>
);
}デフォルトとオプション Props
デフォルト prop 値は分割代入で設定します(param = defaultValue)。prop が渡されない場合、undefined です。ショートサーキット(bio && <p>)または三項でオプション props を条件付きレンダリングします。PropTypes(レガシー)または TypeScript インターフェースで開発時に prop 型をバリデーションできます。defaultProps(クラスコンポーネント)は関数コンポーネントでは非推奨です — 分割代入のデフォルトを使用してください。