SvelteのPropsとは?親子コンポーネントの関係を解説
大平 恵美
大平 恵美
2025-02-06
Svelteの開発で欠かせない「Props」の仕組みを解説します。親コンポーネントと子コンポーネントの関係や、デザインツールのマスターコンポーネントとの違い、CSSのプロパティとの対比など、初心者が混乱しやすいポイントを分かりやすく整理しました。Propsの基本からimportとexportの役割まで、実践的なコード例を交えて詳しく説明します。
あなた:

あなたはプロのフロントエンドエンジニアです。SvelteKitで開発をしています。Propsってなんですか。

ChatGPT

**Props(プロップス)**は、SvelteやReactなどのコンポーネントベースのフレームワークで使用される概念で、コンポーネントにデータを渡すための仕組みです。Propsは「properties(プロパティ)」の略で、親コンポーネントから子コンポーネントに値を渡す際に使われます。


SvelteでのPropsの基本例

1. 子コンポーネントの作成

たとえば、Greeting.svelte というコンポーネントを作るとします。

<script>
  export let name;  // ← これが「Prop」です
</script>

<h1>Hello, {name}!</h1>
  • export let name;
    この記述で、name というPropを受け取る準備ができます。
    nameの型は特に指定しなくても動作しますが、TypeScriptを使う場合は型指定も可能です。

2. 親コンポーネントでの使用

次に、このGreetingコンポーネントを別のファイル(例:App.svelte)で使います。

<script>
  let userName = "Alice";
</script>

<Greeting name={userName} />
  • <Greeting name={userName} />
    ここで、親コンポーネントは userName という変数の値を Greeting に渡しています。
    Greeting 側では、name というPropとして受け取り、Hello, Alice! と表示されます。

ポイント

  1. 親 → 子 への一方向データフロー

    • Propsは基本的に親から子へ一方向に流れます。
    • 子コンポーネント内でPropsを直接書き換えることは避けるべきです。
  2. Propsのデフォルト値

    • もし親から値が渡されなかった場合に備えて、デフォルト値を設定できます。
    <script>
      export let name = "Guest";
    </script>
    
    <h1>Hello, {name}!</h1>
    
  3. 型指定(TypeScriptを使用する場合)

    <script lang="ts">
      export let age: number;
    </script>
    
    <p>Age: {age}</p>
    

まとめ

  • Props = 親から子へデータを渡す手段。
  • export let で宣言することで、子コンポーネントがデータを受け取れる。
  • デフォルト値や型指定も可能。

SvelteKitの開発では、このPropsの概念がコンポーネント間のデータ管理の基本になるので、しっかり理解しておくと良いですね!

Gemini

Props のデフォルト値 Props にデフォルト値を設定することも可能です。子コンポーネント内で

export let propName = defaultValue; のように記述します。

Svelte

<script>
 export let message = 'Welcome!';
</script>

<p>{message}</p>

親コンポーネントから Props が渡されなかった場合、デフォルト値が使用されます。

Props の検証 Props の型や必須項目などを検証することで、コンポーネントの信頼性を高めることができます。PropTypes などのライブラリを使用することで、より詳細な検証を行うことができます。

SvelteKit 特有の Props SvelteKit では、page や params などの Props が自動的に渡されることがあります。これらの Props を利用することで、現在のページの情報や URL パラメータなどを取得することができます。

まとめ Props は、SvelteKit コンポーネント間でデータを効率的に受け渡すための重要な仕組みです。Props を活用することで、コンポーネントの再利用性や保守性を高めることができます。

より詳しい情報や具体的な使用例については、SvelteKit の公式ドキュメントを参照することをおすすめします。

あなた:

CSSを書く時にプロパティ:値で書いたことがあります。これとの違いはなんですか。

ChatGPT:

とても良い質問です!**CSSのプロパティ(property: value;フレームワークのProps(Properties)**は、どちらも「プロパティ」と呼ばれますが、役割も使い方も全く異なるものです。


違いのポイント

項目 CSSのプロパティ フロントエンドのProps(Properties)
役割 要素の**見た目(スタイル)**を制御 コンポーネント間でデータを受け渡すための仕組み
書き方 color: red; のように記述 export let name; で宣言し、<Greeting name="John" />で渡す
適用対象 HTML要素に対して適用 コンポーネントに対して適用
影響する範囲 色、フォント、レイアウトなどのデザイン テキスト、数値、オブジェクトなどのデータ
使用場所 CSSファイル or <style>タグ内 JavaScript(またはSvelteの<script>タグ内)

🎨 CSSのプロパティとは?

CSSのプロパティは、HTML要素のデザインやレイアウトを指定するためのものです。

例: CSSのプロパティ

h1 {
  color: blue;        /* テキストの色を青にする */
  font-size: 24px;    /* フォントサイズを24pxにする */
  margin: 10px;       /* 余白を10px追加する */
}
  • **ここでの「プロパティ」**は colorfont-size など。
  • **「値」**は blue24px など。

CSSは見た目をコントロールするために使います。


🧩 Props(プロパティ)とは?

一方、SvelteのPropsは、親から子コンポーネントへデータを渡すためのものです。

例: SvelteでのProps

<!-- Greeting.svelte -->
<script>
  export let name;  // ← これが「Props」
</script>

<h1>Hello, {name}!</h1>  <!-- ここでデータを表示 -->
<!-- App.svelte(親コンポーネント) -->
<Greeting name="Alice" />  <!-- Propsで「Alice」というデータを渡す -->
  • **ここでの「プロパティ(Props)」**は name です。
  • 親から name="Alice" というデータを渡して、子コンポーネントがそれを表示します。

Propsは見た目の変更ではなく、データの受け渡しに使います。


🚀 具体的な違いをイメージで理解

もし「Tシャツ」を例にすると:

  • CSSのプロパティ → Tシャツの「色」や「サイズ」などのデザインを変えるもの。
    例: color: red;(赤いTシャツにする)

  • Props → Tシャツに書かれた「メッセージ」や「名前」などの情報を渡すもの。
    例: name="John"(Tシャツに「John」とプリントする)


まとめ

  • CSSのプロパティ = 見た目を変えるための設定(色、フォント、余白など)。
  • Props(プロパティ) = コンポーネント間でデータを受け渡す仕組み(テキスト、数値、オブジェクトなど)。

どちらも「プロパティ」という言葉を使いますが、目的が全く違うことがポイントです!

あなた:

親コンポーネントと子コンポーネントの関係について。デザインツールのマスターコンポーネントとインスタンスと混同していた。

ChatGPT

なるほど!デザインツール(FigmaやAdobe XDなど)のマスターコンポーネントと混同していたのですね。それぞれの概念が似ている部分もあるので、混乱するのは自然なことです。でも、理解しておくと今後の開発でとても役立ちます!


🎨 デザインツールの「マスターコンポーネント」 vs. フロントエンドの「親子コンポーネント」

項目 デザインツール(マスターコンポーネント) フロントエンド(親子コンポーネント)
定義 ベースとなるデザインの「元データ」 データの流れ(親→子)で構成されるコンポーネントの階層構造
役割 インスタンスのデザインを一括で管理するための「テンプレート」 データや機能を渡して表示や動作を制御する「構造的な枠組み」
データの流れ 変更はマスターからインスタンスに「一方向」 親から子へ「一方向」にデータが流れるが、イベントで親に伝えることも
変更の影響範囲 マスターを変更するとすべてのインスタンスに反映される 親のPropsを変えると、子コンポーネントに影響が出る
再利用性 デザインの再利用が簡単 UIコンポーネントをコードとして再利用可能

混同しやすいポイント

  • デザインツールのマスターコンポーネント = 「デザインのテンプレート」
  • フロントエンドの子コンポーネント = 「再利用可能なUI部品」

どちらも再利用可能な部品という点で似ていますが、
データの流れ動作の制御という意味では大きな違いがあります。


🚀 イメージで理解する:ボタンの例

1. デザインツールの場合(Figmaなど)

  • マスターコンポーネント(Button Master)
    • ボタンの基本デザイン(色、角丸、フォントサイズなど)を定義。
  • インスタンス(Button Copy)
    • マスターを元にしたコピー。マスターを変えると全部のインスタンスに反映される。

2. フロントエンドの場合(Svelte)

<!-- Button.svelte(子コンポーネント) -->
<script>
  export let label = "Click Me";  // 親から受け取るデータ
</script>

<button>{label}</button>
<!-- Page.svelte(親コンポーネント) -->
<Button label="Submit" />
<Button label="Cancel" />
  • 親コンポーネントButtonに異なるデータ(label)を渡すことで、表示を制御。
  • 子コンポーネントは、受け取ったデータを基に表示するだけ。

ここで重要なのは、子は常に親からデータを受け取る立場ということです。


🎯 まとめ

  • デザインツールでは、マスターコンポーネントが「親」のように振る舞います。
  • フロントエンドでは、親コンポーネントが子コンポーネントに「データを渡す」役割を持ちます。

どちらも「再利用性」を意識した考え方ですが、
データの流れと構造の違いに気づけば、もう混乱することはありません!

これでスッキリしたでしょうか?

あなた:

親コンポーネントであるpage.svelteには を記載。子コンポーネントであるButton.svelteには を記載。importは取り込む、exportは渡すという意味で、これでは親がデータを受け取るみたいな解釈になってしまいます。

ChatGPT:

素晴らしい観察力です!確かに、import(取り込む)export(渡す) という言葉の意味が、Svelteの親子コンポーネントのデータフローと少し混乱を招くことがあります。でも、この違和感を理解することで、より深く仕組みを理解できます!


🚀 ポイントは「データの流れ」と「コードの構造」の違い

  • import / export はコードの「モジュールシステム」に関する話
  • 親から子へのデータの流れは「Props」によるもの

この2つは別の概念ですが、一緒に使うので混同しやすいのです。


親子コンポーネントの関係を整理する

1️⃣ 子コンポーネント(Button.svelte

<script>
  export let label = "Click Me";  // ← 親から受け取るデータ(Props)を「公開」している
</script>

<button>{label}</button>
  • ここでの export は、label という変数を「外部(親)から渡せるように公開する」意味です。
  • 「子が親にデータを渡す」のではなく、「子が親からデータを受け取る準備をしている」イメージ。

2️⃣ 親コンポーネント(Page.svelte

<script>
  import Button from './Button.svelte';  // ← Buttonコンポーネントを「取り込む」
</script>

<Button label="Submit" />  <!-- Propsを通じて「データを渡す」 -->
  • ここでの import は、Buttonコンポーネント(コード全体)を「親が使うために取り込む」という意味です。
  • importは「データの受け取り」ではなく、「再利用するためにコンポーネントを取り込む」だけです。

🎯 わかりやすく例えるなら…

🍱 お弁当の例

  • 子コンポーネント(Button):お弁当箱

    • export let label は「お弁当箱のフタを開けて、親が中身(データ)を入れられるようにする」イメージ。
  • 親コンポーネント(Page):お母さん

    • import Button は「お弁当箱を持ってくる」だけ。
    • <Button label="Submit" /> で「お弁当箱におかず(データ)を詰める」。

まとめ

  • import → 「コンポーネント(箱)そのものを取り込む」ためのもの。
  • export let → 「親がデータ(中身)を入れられるように箱のフタを開ける」イメージ。
  • データの流れは「親から子へ」だけど、exportはそのための「準備」をしているだけ。

これで、言葉の意味と実際の動作の違いがスッキリするはずです! 🚀