Reactのpropsとは?親子コンポーネントのデータ受け渡し入門
Reactのpropsの基本概念から実践的な使い方まで詳しく解説。親子コンポーネント間でのデータ受け渡しの仕組みと活用方法を初心者向けに紹介
みなさん、Reactを学び始めたばかりで「propsって何?」と思ったことはありませんか?
「親コンポーネントから子コンポーネントへのデータ受け渡し」って聞いても、最初はピンと来ないですよね。 でも大丈夫です!propsはReactの基本中の基本で、理解すれば必ず使いこなせるようになります。
この記事では、Reactのpropsについて基本的な概念から実践的な使い方まで、初心者の方にも分かりやすくお伝えします。 具体的なコード例をたくさん使って、親子コンポーネント間でのデータ受け渡しの仕組みを一緒に学んでいきましょう。
propsって何?基本的な考え方
propsは「properties(プロパティ)」の略です。
簡単に言うと、コンポーネント同士で情報をやり取りするための仕組みなんです。
身近な例で理解してみよう
propsの概念を、身近な例で考えてみましょう。
例えば、お母さんが子どもにおやつを渡すとき。 お母さんが親、子どもが子、おやつがpropsです。
// 親コンポーネント(お母さん)
function App() {
return (
<div>
<Welcome name="太郎" />
<Welcome name="花子" />
</div>
);
}
// 子コンポーネント(子ども)
function Welcome(props) {
return <h1>こんにちは、{props.name}さん!</h1>;
}
この例では、name
というpropsを使って、親コンポーネント(App)から子コンポーネント(Welcome)に名前を渡しています。
実行すると、こんな結果になります。
こんにちは、太郎さん!
こんにちは、花子さん!
親から子へ、一方通行で情報が流れているのがポイントです。
propsの重要な特徴
propsには、覚えておきたい特徴があります。
function Welcome(props) {
// ❌ これはエラーになる(propsは変更できない)
// props.name = "新しい名前";
// ✅ 読み取りのみ可能
return <h1>こんにちは、{props.name}さん!</h1>;
}
propsは読み取り専用です。 子コンポーネントが受け取ったpropsを直接変更することはできません。
この制限があることで、データの流れが予測しやすくなり、バグの少ないアプリを作れるんです。
もう一つの特徴は、上から下への一方向の流れです。
function Parent() {
const userName = "田中太郎";
return (
<div>
<Child name={userName} />
</div>
);
}
function Child(props) {
return <p>受け取った名前: {props.name}</p>;
}
親コンポーネントから子コンポーネントへ、常に上から下に情報が流れます。
propsの基本的な使い方
様々な種類のデータをpropsで渡してみましょう。
どんなデータでも渡せるのが、propsの便利なところです。
文字列を渡す場合
文字列は一番シンプルなpropsです。
function App() {
return (
<div>
<UserProfile name="田中太郎" />
<UserProfile name="佐藤花子" />
</div>
);
}
function UserProfile({ name }) {
return (
<div>
<h2>ユーザープロフィール</h2>
<p>名前: {name}</p>
</div>
);
}
ここでは{ name }
という書き方を使っています。
これは「分割代入」という方法で、propsから直接値を取り出せて便利です。
数値を渡す場合
数値を渡すときは、{}
で囲みます。
function App() {
return (
<div>
<Counter initialValue={0} />
<Counter initialValue={10} />
</div>
);
}
function Counter({ initialValue }) {
const [count, setCount] = useState(initialValue);
return (
<div>
<p>カウント: {count}</p>
<button onClick={() => setCount(count + 1)}>
+1
</button>
</div>
);
}
この例では、カウンターの初期値を親から子に渡しています。 一つは0から、もう一つは10からカウントが始まります。
真偽値(true/false)を渡す場合
ボタンの見た目を変える例を見てみましょう。
function App() {
return (
<div>
<Button isPrimary={true} text="メインボタン" />
<Button isPrimary={false} text="サブボタン" />
</div>
);
}
function Button({ isPrimary, text }) {
return (
<button className={isPrimary ? 'btn-primary' : 'btn-secondary'}>
{text}
</button>
);
}
isPrimary
の値によって、ボタンのクラス名が変わります。
これで、見た目の違うボタンを作り分けられます。
配列やオブジェクトを渡す場合
もっと複雑なデータも渡せます。
function App() {
const user = {
name: '田中太郎',
age: 25,
email: 'tanaka@example.com'
};
const hobbies = ['読書', '映画鑑賞', 'プログラミング'];
return (
<div>
<UserCard user={user} hobbies={hobbies} />
</div>
);
}
function UserCard({ user, hobbies }) {
return (
<div>
<h2>{user.name}</h2>
<p>年齢: {user.age}歳</p>
<p>メール: {user.email}</p>
<div>
<h3>趣味</h3>
<ul>
{hobbies.map((hobby, index) => (
<li key={index}>{hobby}</li>
))}
</ul>
</div>
</div>
);
}
オブジェクトや配列を渡すことで、まとまった情報を一度に子コンポーネントに渡せます。
hobbies.map()
で配列の中身を一つずつ表示しています。
key={index}
は、Reactが効率よく画面を更新するために必要な属性です。
propsの受け取り方のパターン
propsを受け取る方法は何通りかあります。
どの方法を選ぶかで、コードの読みやすさが変わってきます。
基本的な受け取り方
最初は、この3つのパターンを覚えておきましょう。
// 方法1: propsオブジェクトとして受け取る
function Welcome(props) {
return <h1>こんにちは、{props.name}さん!</h1>;
}
// 方法2: 分割代入で受け取る(おすすめ)
function Welcome({ name }) {
return <h1>こんにちは、{name}さん!</h1>;
}
// 方法3: 複数のpropsを分割代入で受け取る
function UserProfile({ name, age, email }) {
return (
<div>
<h2>{name}</h2>
<p>年齢: {age}歳</p>
<p>メール: {email}</p>
</div>
);
}
方法2の分割代入がおすすめです。 コードがスッキリして、どのpropsを使っているかが一目で分かります。
デフォルト値を設定する
propsが渡されなかった場合の初期値を設定できます。
// 方法1: 関数の引数でデフォルト値を設定
function Welcome({ name = '匿名ユーザー' }) {
return <h1>こんにちは、{name}さん!</h1>;
}
// 方法2: defaultPropsを使用
function Welcome({ name }) {
return <h1>こんにちは、{name}さん!</h1>;
}
Welcome.defaultProps = {
name: '匿名ユーザー'
};
どちらでも同じ結果になります。
function App() {
return (
<div>
<Welcome name="田中太郎" /> {/* 田中太郎 */}
<Welcome /> {/* 匿名ユーザー */}
</div>
);
}
propsが渡されなかった場合は、デフォルト値が使われます。
残りのpropsをまとめて受け取る
...
を使って、指定していないpropsをまとめて受け取ることもできます。
function Button({ variant, children, ...otherProps }) {
return (
<button
className={`btn btn-${variant}`}
{...otherProps}
>
{children}
</button>
);
}
使用例はこんな感じです。
function App() {
return (
<div>
<Button
variant="primary"
onClick={() => console.log('クリック')}
disabled={false}
>
ボタンのテキスト
</Button>
</div>
);
}
variant
とchildren
以外の属性(onClick
、disabled
など)は、otherProps
にまとめられて、そのまま<button>
要素に渡されます。
関数をpropsとして渡そう
propsでは、関数も渡すことができます。
これを使うと、子コンポーネントから親コンポーネントにデータを送ることができるんです。
基本的な例
まずは、シンプルな例から見てみましょう。
function App() {
const [message, setMessage] = useState('');
const handleButtonClick = (text) => {
setMessage(text);
};
return (
<div>
<p>メッセージ: {message}</p>
<ChildComponent onButtonClick={handleButtonClick} />
</div>
);
}
function ChildComponent({ onButtonClick }) {
return (
<div>
<button onClick={() => onButtonClick('こんにちは')}>
挨拶
</button>
<button onClick={() => onButtonClick('さようなら')}>
お別れ
</button>
</div>
);
}
この仕組みを詳しく見てみましょう。
- 親コンポーネント(App)で
handleButtonClick
関数を定義 - その関数を
onButtonClick
というpropsとして子コンポーネントに渡す - 子コンポーネントでボタンがクリックされたら、受け取った関数を実行
- 親コンポーネントの状態(message)が更新される
これで、子から親へデータを送ることができました!
フォームの実践例
もう少し実践的な例として、ユーザー登録フォームを作ってみましょう。
function App() {
const [users, setUsers] = useState([]);
const handleAddUser = (newUser) => {
setUsers(prevUsers => [...prevUsers, newUser]);
};
return (
<div>
<UserForm onAddUser={handleAddUser} />
<UserList users={users} />
</div>
);
}
まず、親コンポーネントの全体像です。
users
という配列でユーザー一覧を管理しています。
次に、フォームコンポーネントを見てみましょう。
function UserForm({ onAddUser }) {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
onAddUser({ name, email });
setName('');
setEmail('');
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="名前"
/>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="メールアドレス"
/>
<button type="submit">追加</button>
</form>
);
}
フォームが送信されたとき、onAddUser
関数を呼び出して新しいユーザー情報を親に送ります。
最後に、ユーザー一覧を表示するコンポーネントです。
function UserList({ users }) {
return (
<ul>
{users.map((user, index) => (
<li key={index}>{user.name} - {user.email}</li>
))}
</ul>
);
}
これで、フォームで入力したユーザー情報が一覧に追加される仕組みの完成です!
実践的なpropsの活用例
実際のアプリ開発でよく使われるパターンを見てみましょう。
これらの例を参考にすると、より実用的なコンポーネントが作れるようになります。
商品リストの作成
ECサイトでよくある商品リストを作ってみましょう。
まずは、全体の構造をご覧ください。
function App() {
const products = [
{ id: 1, name: 'ノートPC', price: 80000, inStock: true },
{ id: 2, name: 'マウス', price: 3000, inStock: false },
{ id: 3, name: 'キーボード', price: 8000, inStock: true }
];
const handleAddToCart = (productId) => {
console.log(`商品ID: ${productId}をカートに追加`);
};
return (
<div>
<h1>商品一覧</h1>
<ProductList
products={products}
onAddToCart={handleAddToCart}
/>
</div>
);
}
商品データを配列で管理して、カートに追加する関数も用意しています。
次に、商品リストコンポーネントです。
function ProductList({ products, onAddToCart }) {
return (
<div className="product-list">
{products.map(product => (
<ProductCard
key={product.id}
product={product}
onAddToCart={onAddToCart}
/>
))}
</div>
);
}
products
配列をループして、一つずつProductCard
コンポーネントに渡しています。
key={product.id}
で、各商品を識別しています。
最後に、個別の商品カードコンポーネントです。
function ProductCard({ product, onAddToCart }) {
const { id, name, price, inStock } = product;
return (
<div className="product-card">
<h3>{name}</h3>
<p>価格: ¥{price.toLocaleString()}</p>
<p>在庫: {inStock ? '有り' : '無し'}</p>
<button
onClick={() => onAddToCart(id)}
disabled={!inStock}
>
{inStock ? 'カートに追加' : '在庫切れ'}
</button>
</div>
);
}
商品オブジェクトから必要な情報を取り出して表示しています。 在庫がない場合は、ボタンを無効化するのもポイントです。
条件によって表示を変える例
ログイン状態によって画面を切り替える例も見てみましょう。
function App() {
const [user, setUser] = useState(null);
const handleLogin = (userData) => {
setUser(userData);
};
const handleLogout = () => {
setUser(null);
};
return (
<div>
<Header user={user} onLogout={handleLogout} />
<main>
{user ? (
<Dashboard user={user} />
) : (
<LoginForm onLogin={handleLogin} />
)}
</main>
</div>
);
}
user
の状態によって、ダッシュボードかログインフォームかを切り替えています。
ヘッダーコンポーネントでは、ユーザー情報の表示を制御します。
function Header({ user, onLogout }) {
return (
<header>
<h1>マイアプリ</h1>
{user ? (
<div>
<span>ようこそ、{user.name}さん</span>
<button onClick={onLogout}>ログアウト</button>
</div>
) : (
<span>ログインしてください</span>
)}
</header>
);
}
ダッシュボードでは、さらに細かいコンポーネントに分けています。
function Dashboard({ user }) {
return (
<div>
<h2>ダッシュボード</h2>
<UserProfile user={user} />
<RecentActivity userId={user.id} />
</div>
);
}
function UserProfile({ user }) {
return (
<div>
<h3>プロフィール</h3>
<p>名前: {user.name}</p>
<p>メール: {user.email}</p>
</div>
);
}
このように、propsを使ってコンポーネントを細かく分けることで、再利用しやすいコードになります。
propsを使う時の注意点
propsを使う際に気をつけるべきポイントをご紹介します。
これらを意識すると、より良いコードが書けるようになります。
分かりやすい命名をしよう
propsの名前は、見ただけで何を表すかが分かるものにしましょう。
// ✅ 良い例:分かりやすい名前
function UserCard({ userName, userAge, isActive }) {
return (
<div>
<p>名前: {userName}</p>
<p>年齢: {userAge}歳</p>
<p>状態: {isActive ? 'アクティブ' : '非アクティブ'}</p>
</div>
);
}
// ❌ 避けるべき例:意味が分からない名前
function UserCard({ a, b, c }) {
return (
<div>
<p>名前: {a}</p>
<p>年齢: {b}歳</p>
<p>状態: {c ? 'アクティブ' : '非アクティブ'}</p>
</div>
);
}
後から見直したときに、何を表しているかがすぐに分かる名前をつけましょう。
propsが多すぎる場合は整理しよう
propsの数が多くなりすぎたら、オブジェクトにまとめることを検討してみてください。
// ❌ プロパティが多すぎる場合
function UserProfile({
name, age, email, phone, address, city, country,
occupation, company, salary, hobbies, skills
}) {
// 複雑になりがち
}
// ✅ オブジェクトにまとめる
function UserProfile({ user, contact, employment }) {
return (
<div>
<h2>{user.name}</h2>
<p>年齢: {user.age}歳</p>
<p>メール: {contact.email}</p>
<p>電話: {contact.phone}</p>
<p>職業: {employment.occupation}</p>
<p>会社: {employment.company}</p>
</div>
);
}
関連する情報をグループ化することで、コードが読みやすくなります。
必要ないpropsは渡さない
すべてのコンポーネントに同じpropsを渡す必要はありません。
// ❌ 不必要にpropsを渡す
function App() {
const appTitle = "マイアプリ";
return (
<div>
<Header title={appTitle} />
<Main title={appTitle} />
<Footer title={appTitle} />
</div>
);
}
// ✅ 必要な場所でのみpropsを使用
function App() {
const appTitle = "マイアプリ";
return (
<div>
<Header title={appTitle} />
<Main />
<Footer />
</div>
);
}
実際にタイトルを使うコンポーネントにだけ、propsを渡すようにしましょう。
まとめ
Reactのpropsは、コンポーネント間でデータをやり取りするための重要な仕組みです。
親から子への一方向の流れを理解することで、アプリケーションの構造が明確になり、予測しやすいコードが書けるようになります。
覚えておきたい重要なポイントはこちらです。
- propsは読み取り専用で、子コンポーネントが直接変更することはできない
- 分割代入を使って受け取ると、コードがスッキリする
- 関数をpropsとして渡すことで、子から親にデータを送ることができる
- propsの名前は分かりやすくつけて、必要な場所でのみ使用する
最初は複雑に感じるかもしれませんが、実際にコードを書いて練習することで必ず理解できます。
ぜひ今回の例を参考にして、自分なりのコンポーネントを作ってpropsの活用に慣れてみてください。 きっと、Reactの便利さを実感できるはずです!