$props
コンポーネントへの入力は props (プロパティの省略形) と呼ばれます。属性を要素に渡すのと同じように、props をコンポーネントに渡します:
<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 を受け取ることができます...
<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 を 分割代入 することが多いです:
<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 を設定しない場合に使用されます (フォールバック値がなく、親コンポーネントから設定されない場合、その値は undefined になります):
let { let adjective: anyadjective = 'happy' } = function $props(): any
namespace $props
Declares the props that a component accepts. Example:
let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $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
namespace $props
Declares the props that a component accepts. Example:
let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();
$props();Rest props
最後に、rest property を使用して、他のすべての props を取得できます:
let { let a: anya, let b: anyb, let c: anyc, ...let others: anyothers } = function $props(): any
namespace $props
Declares the props that a component accepts. Example:
let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();
$props();Updating props
コンポーネント内の props に対する参照は、その props 自体が更新されると更新されます — App.svelte の count が変更されると、それは Child.svelte 内でも変更されます。ただし、子コンポーネントは一時的に prop の値を上書きすることができ、これは保存されない一時的な state として便利です (demo):
<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} /><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 が通常のオブジェクトの場合、変異させても何の効果もありません (デモ):
<script>
import Child from './Child.svelte';
</script>
<Child object={{ count: 0 }} /><script lang="ts">
import Child from './Child.svelte';
</script>
<Child object={{ count: 0 }} /><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)しているためです (デモ):
<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} /><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)しても更新は発生しません (デモ)
<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 を簡単に発見できるようになります。
$props.id()
This rune, added in version 5.20.0, generates an ID that is unique to the current component instance. When hydrating a server-rendered component, the value will be consistent between server and client.
This is useful for linking elements via attributes like for and aria-labelledby.
<script>
const uid = $props.id();
</script>
<form>
<label for="{uid}-firstname">First Name: </label>
<input id="{uid}-firstname" type="text" />
<label for="{uid}-lastname">Last Name: </label>
<input id="{uid}-lastname" type="text" />
</form>