🐋

Svelte5の7つのRunesを理解する

2025/02/18に公開

概要

Runeとは、Svelte5から導入された特殊な記述方法です。先頭に $ をつけて書きます。
Runeは付加的な機能なので新しく学ぶ必要がありますが、既存のコードをよりシンプルに書くことができます。7つあるRuneを解説します。

参照

$state

$state は、リアクティブなステートを宣言します。値が変わったとき、参照している場所でその変更を検知できます。コンポーネントのトップレベルにある let 宣言でのみ機能します。

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

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

https://svelte.dev/playground/55e477bd24e24886828db4a957690aae?version=5.20.0

$state は .svelte ファイルを越えて参照でき、これまでの store の代わりとして使うことができます。

counter.svelte.js
export const counter = $state({
  count: 0,
});
App.svelte
<script>
  import {counter} from './counter.svelte.js';
</script>

<button onclick={() => counter.count += 1}>
  count:{counter.count}
</button>

https://svelte.dev/playground/c9f16cca64e94e2a90659f45ec07e4e8?version=5.19.3

$derived

$derived は、他のリアクティブな値($state)からの派生を宣言できます。
たとえば、count の2倍の値を定義する doubled はこう書きます。

<script>
  let count = $state(0);
  let doubled = $derived(count * 2);
</script>

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

<p>Doubled: {doubled}</p>

https://svelte.dev/playground/b289347346544412b4ade6baa7564f65?version=5.20.0

width と height から面積を計算するサンプルです。
(後ほど説明する $props を使用してます)
https://svelte.dev/playground/4f6445e9c30449bcb8898338e24efd55?version=5.20.0

$effect

$effect は、関数内で使用している $state や $deriverd を監視し、変更があるたびに再実行します。外部システムと同期するのに便利ですが、多用すると依存関係が複雑になるので注意が必要です。

$deriverd のサンプルを $effect で書き直すと、以下のようになります。

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

  $effect(() => {
    doubled = count * 2;
  });
</script>

<button onclick={() => count += 1}>
  count:{count}
</button>
<p>Doubled: {doubled}</p>

https://svelte.dev/playground/33ce7ad3ea8242458f570f892b67d328?version=5.20.0

ライフサイクル関数として onMount の代わりに使用できます。
https://svelte.dev/playground/75f519531ed14ba9ba90c25febad0f4a?version=5.20.0

$props

$props は、コンポーネントへの入力に使用します。コンポーネント側では分割代入を使用するのが一般的です。

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

<Component />
<Component name='World' />
Component.svelte
<script>
  let { name='default' } = $props();
</script>

<h1>Hello {name}!</h1>

https://svelte.dev/playground/d06204c690a742188e4fb2329e6fd9e8?version=5.20.0

コンポーネントにコンテンツを渡す場合、これまではslotを使用してきました。Svelte5からは、snippet を使用します。コンポーネントタグの内部に書いたコンテンツは「children」snnipet として扱われ、$propsで受け取ることが可能です。

App.svelte
<script>
  import Card from './Card.svelte';
  let name = 'world';
</script>
	
<Card>
  <h1>Hello {name}!</h1>
  <p>This is inside card.</p>
</Card>
Card.svelte
<script>
  let { children } = $props();
</script>

<div class="card">
  {@render children()}
</div>

https://svelte.dev/playground/890068476569440c9c8ce4544c9bd7a8?version=5.20.0

$bindable

基本的にプロパティはコンポーネントの親から子に値を渡しますが、$bindable を使用することで、子から親に値を渡すことも可能です。多用せず、必要な場所にのみ使用することが推奨されてます。

子コンポーネントでテキストをinputするサンプルです。渡す値には bind: をつけます。

App.svelte
<script>
  import Input from './Input.svelte';
  let name = $state('world');
</script>

<Input bind:text={name}/>
<h1>Hello {name}!</h1>
Input.svelte
<script>
  let { text=$bindable() } = $props();
</script>

<input type="text" bind:value={text} />

https://svelte.dev/playground/0ca0969e12894a1da8611f517a680513?version=5.20.0

$inspect

$inspect は、開発で使う検査用ルーンです。値を監視し、変更があったら console.log を実行します。

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

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

クリックしてcountを更新すると、以下のようなconsoleが出力されます。

init 0
update 1
update 2
update 3
...

$host

$hostは、コンポーネントをカスタム要素(Web Components)としてコンパイルする時に使用し、host要素にアクセスできます。
ここでは、公式のDemoを共有するにとどめます。
https://svelte.dev/playground/untitled?version=5.20.1#H4sIAAAAAAAAE41Ry2rDMBD8FSECtqkTt1fHFpSSL-ix7sFRNkTEXglrnTYY_3uRlDgxTaEHIfYxs7szA9-rBizPPwZOZwM89wmecqxbF70as7InaMjltrWFR3mpkQDJ8pwXVnbKkKiwItUa3RGLVtk7gTHQXRDR2lXda4CY1D0SK9nCUk0QPyfrCovsRoNFe17aQOAwGncgO2gBqRzihJXiQrEs2csYOhQ-7HgKHaLIbpRhhBG-I2eD_8ciM4KnnOCbeE5dD2P6h0Dz0-Yi_arNhPLJXBtSGi2TvSXdbpqwdsXvjuYsC1veabvvUTog2ylrapKH2G2XsMFLS4uDthQnq2t1cwKkGOGLvYU5PvaQxLsxOkPmsm97Io1Mo2yUPF6VnOZFkw1RMoopKLKAE_9gmGxyDFMwMcwN-Bx_ABXQWmOtAgAA

まとめ

Svelte5から導入された7つのRuneを解説しました。よく使用する機能を中心に紹介したので、特殊なシチュエーションでの使用方法を深掘りしたい場合、公式ドキュメントを参照ください。

Discussion