メインコンテンツへスキップ

これまでは、状態という観点からリアクティビティについて説明してきました。しかし、それは方程式の半分に過ぎません。状態は、何かがそれに反応しなければリアクティブではなく、単なるキラキラした変数です。

反応するものはエフェクトと呼ばれます。既にエフェクトに出会っています。Svelteは、状態の変化に応じてDOMを更新するために、あなたの代わりにエフェクトを作成しますが、`$effect`ルーンを使用して独自のエフェクトを作成することもできます。

ほとんどの場合、使用するべきではありません。`$effect`は、頻繁に使用するものではなく、脱出ハッチとして考えるのが最適です。例えば、副作用をイベントハンドラに置くことができる場合は、ほとんどの場合、それが優先されます。

コンポーネントがマウントされてから経過時間を追跡するために`setInterval`を使用したいとしましょう。エフェクトを作成します。

アプリ
<script>
	let elapsed = $state(0);
	let interval = $state(1000);

	$effect(() => {
		setInterval(() => {
			elapsed += 1;
		}, interval);
	});
</script>

「スピードアップ」ボタンを数回クリックすると、`interval`が小さくなるたびに`setInterval`を呼び出しているので、`elapsed`が速くなります。

次に「スローダウン」ボタンをクリックすると…うまくいきません。それは、エフェクトが更新されたときに古いインターバルをクリアしていないためです。クリーンアップ関数 を返すことで修正できます。

アプリ
$effect(() => {
	const id = setInterval(() => {
		elapsed += 1;
	}, interval);

	return () => {
		clearInterval(id);
	};
});

クリーンアップ関数は、`interval`が変更されたときにエフェクト関数が再実行される直前、およびコンポーネントが破棄されたときに呼び出されます。

エフェクト関数が実行時に状態を読み取らない場合、コンポーネントのマウント時に一度だけ実行されます。

エフェクトはサーバーサイドレンダリング中は実行されません。

GitHubでこのページを編集

1
2
3
4
5
6
7
8
9
10
<script>
	let elapsed = $state(0);
	let interval = $state(1000);
</script>
 
<button onclick={() => interval /= 2}>speed up</button>
<button onclick={() => interval *= 2}>slow down</button>
 
<p>elapsed: {elapsed}</p>