Skip to main content

$props

コンポーネントへの入力は props (プロパティの省略形) と呼ばれます。属性を要素に渡すのと同じように、props をコンポーネントに渡します:

App
<script>
	import MyComponent from './MyComponent.svelte';
</script>

<MyComponent adjective="cool" />
<script lang="ts">
	import MyComponent from './MyComponent.svelte';
</script>

<MyComponent adjective="cool" />

それに対し、MyComponent.svelte の内部では、$props rune を使用して props を受け取ることができます...

MyComponent
<script>
	let props = $props();
</script>

<p>this component is {props.adjective}</p>
<script lang="ts">
	let props = $props();
</script>

<p>this component is {props.adjective}</p>

...ただし、一般的には props を 分割代入 することが多いです:

MyComponent
<script>
	let { adjective } = $props();
</script>

<p>this component is {adjective}</p>
<script lang="ts">
	let { adjective } = $props();
</script>

<p>this component is {adjective}</p>

Fallback values

分割代入を使用するとフォールバック値を宣言できます。これは親コンポーネントが特定の props を設定しない場合に使用されます:

let { let adjective: anyadjective = 'happy' } = function $props(): any

Declares the props that a component accepts. Example:

let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();

https://svelte.dev/docs/svelte/$props

$props
();

フォールバック値はリアクティブな state proxy には変換されません (Updating props を参照してください)

Renaming props

分割代入を使用して props をリネームすることもできます。これは元の props の名前が無効な識別子や super のような JavaScript キーワードである場合に必要となります:

let { super: let trouper: anytrouper = 'lights are gonna find me' } = function $props(): any

Declares the props that a component accepts. Example:

let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();

https://svelte.dev/docs/svelte/$props

$props
();

Rest props

最後に、rest property を使用して、他のすべての props を取得できます:

let { let a: anya, let b: anyb, let c: anyc, ...let others: anyothers } = function $props(): any

Declares the props that a component accepts. Example:

let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();

https://svelte.dev/docs/svelte/$props

$props
();

Updating props

コンポーネント内の props に対する参照は、その props 自体が更新されると更新されます — App.sveltecount が変更されると、それは Child.svelte 内でも変更されます。ただし、子コンポーネントは一時的に prop の値を上書きすることができ、これは保存されない一時的な state として便利です (demo):

App
<script>
	import Child from './Child.svelte';

	let count = $state(0);
</script>

<button onclick={() => (count += 1)}>
	clicks (parent): {count}
</button>

<Child {count} />
<script lang="ts">
	import Child from './Child.svelte';

	let count = $state(0);
</script>

<button onclick={() => (count += 1)}>
	clicks (parent): {count}
</button>

<Child {count} />
Child
<script>
	let { count } = $props();
</script>

<button onclick={() => (count += 1)}>
	clicks (child): {count}
</button>
<script lang="ts">
	let { count } = $props();
</script>

<button onclick={() => (count += 1)}>
	clicks (child): {count}
</button>

props は一時的に再代入(reassign)することができます。一方で、bindable でない限り変異(mutate)すべきではありません。

prop が通常のオブジェクトの場合、変異させても何の効果もありません (デモ):

App
<script>
	import Child from './Child.svelte';
</script>

<Child object={{ count: 0 }} />
<script lang="ts">
	import Child from './Child.svelte';
</script>

<Child object={{ count: 0 }} />
Child
<script>
	let { object } = $props();
</script>

<button onclick={() => {
	// has no effect
	object.count += 1
}}>
	clicks: {object.count}
</button>
<script lang="ts">
	let { object } = $props();
</script>

<button onclick={() => {
	// has no effect
	object.count += 1
}}>
	clicks: {object.count}
</button>

props がリアクティブな state proxy の場合、変異(mutation)は反映されますが、ownership_invalid_mutation 警告が表示されます。これは、そのコンポーネントが「所有していない」state を変異(mutate)しているためです (デモ):

App
<script>
	import Child from './Child.svelte';

	let object = $state({count: 0});
</script>

<Child {object} />
<script lang="ts">
	import Child from './Child.svelte';

	let object = $state({count: 0});
</script>

<Child {object} />
Child
<script>
	let { object } = $props();
</script>

<button onclick={() => {
	// will cause the count below to update,
	// but with a warning. Don't mutate
	// objects you don't own!
	object.count += 1
}}>
	clicks: {object.count}
</button>
<script lang="ts">
	let { object } = $props();
</script>

<button onclick={() => {
	// will cause the count below to update,
	// but with a warning. Don't mutate
	// objects you don't own!
	object.count += 1
}}>
	clicks: {object.count}
</button>

$bindable として宣言されていない props のフォールバック値はそのままです — リアクティブな state proxy には変換されません — つまり変異(mutation)しても更新は発生しません (デモ)

Child
<script>
	let { object = { count: 0 } } = $props();
</script>

<button onclick={() => {
	// has no effect if the fallback value is used
	object.count += 1
}}>
	clicks: {object.count}
</button>
<script lang="ts">
	let { object = { count: 0 } } = $props();
</script>

<button onclick={() => {
	// has no effect if the fallback value is used
	object.count += 1
}}>
	clicks: {object.count}
</button>

要約: props を変異(mutate)しないでください。変更を伝えるためにコールバック props を使用するか、親と子が同じオブジェクトを共有する必要がある場合は $bindable rune を使用してください。

Type safety

他の変数宣言と同様に、props にアノテーションを付けることでコンポーネントに型安全性を追加できます。TypeScript では次のようになります...

<script lang="ts">
	let { adjective }: { adjective: string } = $props();
</script>

...一方、JSDoc では次のようにできます:

<script>
	/** @type {{ adjective: string }} */
	let { adjective } = $props();
</script>

もちろん、型宣言をアノテーションから分離することもできます:

<script lang="ts">
	interface Props {
		adjective: string;
	}

	let { adjective }: Props = $props();
</script>

ネイティブ DOM 要素用のインターフェースは svelte/elements モジュールで提供されています (Typing wrapper components を参照してください)

型を追加することをお勧めします。これにより、コンポーネントを使用する人々が、渡すべき props を簡単に発見できるようになります。

Edit this page on GitHub

previous next