Propsでコンポーネントに値を渡そう
プロ太先生~。今日はReactのコンポーネントにPropsを使ってデータを渡す方法についての授業ですよね?よろしくお願いします!!
はい、OZくん。Propsはコンポーネントに情報を渡すための仕組みです。これによって、コンポーネントの見た目や動作を柔軟に変更することができるようになります。まず、こんなコンポーネントがあるとしましょう。
import "./ColorComponent.css";
const ColorComponent = (props) => {
return (
<div className={`color-box ${props.colorClass}`}>
<h3>This is a color box</h3>
</div>
);
};
export default ColorComponent;
ここではPropsのcolorClass
を使って、divタグのクラス名を動的に変更しています。これによって、コンポーネントの色を変えることができます。
関数の引数としてprops
という変数が受け取られています。props
には、ColorComponentを使う側で渡されたデータが格納されます。例えば、colorClass
というPropsを渡せば、props.colorClass
でその値にアクセスできるようになります。
実際にColorComponentを使う側のコードを見てみましょう。
import ColorComponent from "./ColorComponent";
const App = () => {
return (
<div>
<ColorComponent colorClass="blue" />
<ColorComponent colorClass="red" />
<ColorComponent colorClass="green" />
</div>
);
};
export default App;
ここでは、3つのColorComponentを使っています。
それぞれにcolorClass
というPropsを渡しています。<ColorComponent colorClass="blue" />
の場合、props.colorClass
の値が"blue"
になります。
同様に、"red"
と"green"
が渡されています。
そしてColorComponent.cssには以下のようなスタイルを定義します。
.color-box {
padding: 20px;
border-radius: 8px;
text-align: center;
}
.color-box.blue {
background-color: #ADD8E6;
color: #1E90FF;
}
.color-box.red {
background-color: #FF6961;
color: #DC143C;
}
.color-box.green {
background-color: #90EE90;
color: #006400;
}
なるほど!Propsでクラス名を動的に渡せると、デザインが自由に変えられるんですね。
分割代入で書いてみよう
そしてさらに、JavaScriptの「分割代入」という機能を使うと、もっと簡単に書けます。例えば、今は(props)
と書いていますが、これを({ colorClass })
と書き換えることができます。
const ColorComponent = ({ colorClass }) => {
return (
<div className={`color-box ${colorClass}`}>
<h3>This is a color box</h3>
</div>
);
};
こうすると、props
というオブジェクト全体を受け取る代わりに、必要なcolorClass
だけを直接受け取ることができるんです。これでコードがすっきりして、何が渡されているのか一目でわかりやすくなりますね!
なるほど、分割代入って便利ですね!じゃあ、もし他のPropsも渡したい場合はどうなるんですか?
いい質問です。では、新しくsize
というPropsを追加して、色だけでなく大きさも変えたいとしましょう。size
には "small"
や "large"
などの値を渡して、コンポーネントの見た目を調整できますよ。コードを見てみましょう。
import "./ColorComponent.css";
const ColorComponent = ({ colorClass, size }) => {
return (
<div className={`color-box ${colorClass} ${size}`}>
<h3>This is a color box</h3>
</div>
);
};
export default ColorComponent;
これで、size
というPropsも受け取れるようになりました。次に、App
コンポーネント側で、ColorComponent
にsize
を渡してみましょう。
import ColorComponent from "./components/Child";
const App = () => {
return (
<div>
<ColorComponent colorClass="blue" size="small" />
<ColorComponent colorClass="red" size="large" />
<ColorComponent colorClass="green" size="small" />
</div>
);
};
export default App;
これで、各ColorComponent
に対して色だけでなく、大きさも指定できます。CSS側でもサイズに応じたスタイルを追加します。ちなみにCSSは以下のようにしています。
.color-box {
padding: 20px;
border-radius: 8px;
text-align: center;
}
.color-box.blue {
background-color: #add8e6;
color: #1e90ff;
}
.color-box.red {
background-color: #ff6961;
color: #dc143c;
}
.color-box.green {
background-color: #90ee90;
color: #006400;
}
.color-box.small {
width: 50%;
height: 100px;
}
.color-box.large {
width: 90%;
height: 200px;
}
なるほど、Propsを増やしてどんどんカスタマイズできるんですね。これなら、このsize
やcolorClass
みたいに、必要な値が増えてきても、すっきりしたコードのままでいられますね。分割代入、便利です。でも、ここで復習しておきたいです!
分割代入を復習しておこう
そうですね。では、ここで少し復習として、分割代入の仕組みについて整理しておきましょう。分割代入は、オブジェクトや配列の中身を簡単に取り出すための便利な構文です。ReactのPropsでも使えますが、まずはシンプルな例で見てみましょう。
const user = {
name: "OZ",
age: 17,
club: "badminton",
};
このuser
オブジェクトからname
とage
だけを取り出したいとき、通常ならこう書きます。
const name = user.name;
const age = user.age;
これでも取り出せますが、分割代入を使うともっと短く、こんな風に書けます。
const { name, age } = user;
ここで、const { name, age } = user;
と書くと、「userの中からname
とage
というデータだけを取り出して、個別に変数として使えるようにする」という意味になります。
具体的には、「name」と「age」だけを取り出して、それぞれ別の小箱に入れるような感じです。
const name = "OZ"; // userから取り出されたname
const age = 17; // userから取り出されたage
では、この分割代入のイメージを使って、Propsでも同じように考えてみましょう。
たとえば、先ほどのColorComponent
に渡されるPropsを思い出してください。
ColorComponentは、colorClass
とsize
という2つのデータをPropsとして受け取ります。
<ColorComponent colorClass="blue" size="large" />
このとき、ReactはColorComponent
に渡されたデータを一つのオブジェクトとしてまとめ、関数の引数props
に詰めて渡しています。props
はこんな箱のような状態です。
props
├── colorClass: "blue"
└── size: "large"
通常なら、この中のcolorClass
やsize
にアクセスするために、props.colorClass
やprops.size
と書きます。でも、分割代入を使うと、わざわざprops.
と書かなくても、直接値を取り出せるんです!
分割代入を使った書き方
const ColorComponent = ({ colorClass, size }) => {
return (
<div className={`color-box ${colorClass} ${size}`}>
<h3>This is a color box</h3>
</div>
);
};
ここで、({ colorClass, size })
と書くことで、props
という箱からcolorClass
とsize
だけを抜き出し、直接使える状態にしています。イメージ的には、Propsからそれぞれのデータを取り出して、別々の小箱に分ける感じです。
const colorClass = "blue"; // propsから取り出されたcolorClass
const size = "large"; // propsから取り出されたsize
こうすることで、props
の中身を使うときにprops.
と書かずに済むので、コードがすっきりして読みやすくなりますね!
Propsにいろんな種類の値を渡してみよう
OZくん、さっきのcolorClass
の例でPropsの使い方は少し理解できたかな?
ちなみに、Propsは、文字列だけじゃなくて、数値や関数、ブール値、オブジェクトなど、いろいろな種類の値を渡すことができるんです。実際に以下のような画面を作る具体的なコードで見てみましょう。
import "./ColorComponent.css";
// Propsの分割代入とデフォルト値の設定
const ColorComponent = ({
colorClass = "green", // デフォルトで "green" を設定
num,
fn,
isVisible = false, // デフォルトで false を設定
user = { name: "NoName", age: 0 }, // デフォルトのオブジェクト
}) => {
return (
<div className={`color-box ${colorClass}`}>
<h3>This is a Color Box</h3>
<p>Number: {num}</p>
<p>Message: {fn("こんにちは!")}</p>
<p>Visibility: {isVisible ? "Visible" : "Hidden"}</p>
<p>User: {user.name}, Age: {user.age}</p>
</div>
);
};
export default ColorComponent;
うわ!長いコードになってきましたね。それぞれのPropsの役割を教えてください!
もちろんです!ここではPropsを分割代入で受け取り、それぞれにデフォルト値を設定しています。
colorClass
:親コンポーネントから渡される色の名前です。colorClass
が渡されなければデフォルトで"green"
になります。num
:数値を受け取るPropsです。ここには数値を直接渡すことができます。fn
:関数を受け取るPropsです。親コンポーネントから関数を渡すことで、子コンポーネント内で関数を呼び出せるようになります。isVisible
:ブール値を受け取るPropsで、true
またはfalse
のいずれかになります。デフォルトでfalse
になっていて、渡されればその値を使います。user
:オブジェクトを受け取るPropsで、ここではname
とage
を持つオブジェクトを想定しています。親からオブジェクトが渡されなければ、{ name: "NoName", age: 0 }
というデフォルトのオブジェクトが使われます。
なるほど!Propsにデフォルト値を設定すると、親からの値がなくてもエラーにならずに使えるんですね!
そうなんです。デフォルト値のおかげで、コンポーネントが安定して動作します。
例えば、App
コンポーネントで以下のようにPropsを渡してみましょう。
import ColorComponent from "./ColorComponent";
const App = () => {
const greet = (text) => {
return `挨拶するね! ${text}!`;
};
return (
<div>
<ColorComponent
colorClass="blue"
num={123}
fn={greet}
isVisible={true}
user={{ name: "OZ", age: 17 }}
/>
</div>
);
};
export default App;
このコードだと、Propsが渡されるのは次のような形ですね!
colorClass
:"blue"
num
:123
fn
:greet関数isVisible
:true
user
:{ name: "OZ", age: 17 }
その通りです!これで、ColorComponent
内でそれぞれのPropsを使って表示したり、動作させたりできます。デフォルト値も設定してあるので、親から渡されなかった場合でも問題なく動作します。
なるほど!理解できました!ただ、渡すpropsの値が多いと少しコードが読みにくい感じはしますよね、、、。
スプレッド構文でPropsを渡す
その言葉待っていました!実はスプレッド構文を使うと、オブジェクトの内容を一度に展開してPropsとして渡すことができ、コードを読みやすくできますよ。たとえば、以下のように書けます。
import ColorComponent from "./ColorComponent";
const App = () => {
const user = { name: "OZ", age: 17 };
const componentProps = {
colorClass: "blue",
num: 123,
fn: (text) => `挨拶するね! ${text}!`,
isVisible: true,
user,
};
return (
<div>
<ColorComponent {...componentProps} />
</div>
);
};
export default App;
{...componentProps}
でPropsをまとめて渡しているんですね!便利!
その通り!このスプレッド構文を使うことで、Propsが多い場合もコードがすっきりして、まとめて管理しやすくなります。コンポーネントに渡す内容を一箇所にまとめておけるので、修正もしやすくなりますね。
Propsの重要なポイント:読み取り専用と一方通行
OZくん、最後にPropsに関する大事なポイントを話しておきます。ReactのPropsは「読み取り専用」であり、「親から子へ一方通行」という特徴を持っています。
つまり、Propsとして渡されたデータは子コンポーネントの中で変更することができないんです。
ええ、どういうことですか?
じゃあ、例を見てみましょう。
const Hello = (props) => {
// POINT propsは読み取り専用
// props.name = 'Bob';
// エラーが発生!
return (
<div>
<h3>Hello {props.name}</h3>
</div>
);
};
export default Hello;
ここでは、props.name
に新しい値を代入しようとするとエラーが発生しています。Reactの設計上、Propsの値は変更できないように守られているんです。これはコンポーネント間のデータフローを安定させるための重要なルールなので覚えておきましょう!!
Propsは親から渡されるだけで、子から変更することはできないんですね!了解です!
これによって、コンポーネントの役割が明確になって、予期しないデータの変更が防止できるんです。これはReactの「一方向データフロー」の考え方といって、データの流れが親から子にだけ伝わる仕組みになっているんです。
特別なプロパティ:props.children
を使いこなそう!
最後に、props.children
について説明しますね。もう少しです!頑張ってください!
はい!頑張ります!
props.children
は、特別なプロパティで、コンポーネントの中に他の要素を「挟む」ことで渡せます。たとえば、<Greeting>
というコンポーネントを作ったとします。このGreeting
の中にメッセージや他の要素を自由に挿入できるようにします。
要素を「挟む」ってどういうことですか?
具体例を見てみましょう!まず、以下のようにGreeting
というコンポーネントを作ります。
const Greeting = (props) => {
return (
<div>
<h2>Welcome!</h2>
<div>{props.children}</div>
</div>
);
};
export default Greeting;
このGreeting
コンポーネントは、props.children
というプロパティを使って、呼び出し元から渡された要素を受け取る仕組みになっています。次に、このGreeting
を使ってみよう。
<Greeting>
<p>こんにちは!これがGreetingコンポーネントの内部に表示される内容です。</p>
</Greeting>
<Greeting>
の中に<p>
タグを挟んでいますね。もしかして、こうやって挟むだけで、props.children
にその内容が渡されるんですか?
その通り!この場合、props.children
には<p>こんにちは!これがGreetingコンポーネントの内部に表示される内容です。</p>
が入ります。この結果、Greeting
コンポーネントは以下のようにレンダリングされますよ。
<div>
<h2>Welcome!</h2>
<div>
<p>こんにちは!これがGreetingコンポーネントの内部に表示される内容です。</p>
</div>
</div>
なるほど!props.children
を使うと、コンポーネントの内容を外から自由に変更できるんですね。便利です!!でも、普通のpropsとprops.childrenもどっちも何かを受け渡しに使うことはわかったんですが、2つの違いがちょっとわかりません、、、。
いい質問ですね、では、props
とprops.children
にはそれぞれ役割があるから、その違いを整理しておきましょう!!
props
について
まず、props
はコンポーネントに特定の「データ」や「設定」を渡すために使われます。たとえば、Greeting
コンポーネントに「名前」を渡したいときは、name
というprops
を設定するんです。
const Greeting = (props) => {
return <h2>Hello, {props.name}!</h2>;
};
そして、Greeting
を使うときにname
プロパティで値を渡します。
<Greeting name="OZ" />
なるほど、props.name
を使って「OZ」という名前が渡されるんでしたね!props
はこうやって設定を渡す感じでした!分割代入もできましたよね!
props.children
について
一方で、props.children
は「コンポーネントの中に挟む要素」を受け取る特別なprops
です。たとえば、MessageBox
というコンポーネントを作って、その中にメッセージや他の要素を自由に挿入できるようにします。
const MessageBox = (props) => {
return (
<div className="message-box">
<h3>メッセージ:</h3>
<div>{props.children}</div>
</div>
);
};
そして、MessageBox
を使うときに中に要素を挟みます。
<MessageBox>
<p>これは重要なお知らせです!</p>
</MessageBox>
この場合、props.children
には<p>これは重要なお知らせです!</p>
が入るんでしたね!
props
とprops.children
の違いを整理しよう!
なるほど、なんとなく違いが見えてきました!僕なりに、props
とprops.children
の違いをまとめてみますね!!
props
: コンポーネントに「設定」や「データ」を渡すためのもの。属性として渡す値を指す。- 例:
<Greeting name="OZ" />
props.name
で「OZ」を取得
- 例:
props.children
: コンポーネントの「中に挟む要素」を受け取るための特別なprops
。props.children
は、任意のタグや他のコンポーネントをそのまま渡せる
例)
<MessageBox>
<p>これは重要なお知らせです!</p>
</MessageBox>
→props.children
で<p>これは重要なお知らせです!</p>
を取得
すばらしいまとめです!!成長しましたね!!先生は嬉しいです。
まとめ
Propsを使うと、コンポーネントにさまざまなデータを柔軟に渡し、見た目や動作をカスタマイズできます。分割代入を用いて、必要なデータをすっきりと受け取ることができ、コードの読みやすさも向上します。また、デフォルト値を設定することで、親からのデータがない場合でも安定した動作が可能です。Propsの活用方法を理解し、Reactのコンポーネント設計の幅を広げていきましょう!