Skip to main content
Basic Svelte
Introduction
Reactivity
Props
Logic
Events
Bindings
Classes and styles
Actions
Transitions
Advanced Svelte
Advanced reactivity
Reusing content
Motion
Advanced bindings
Advanced transitions
Context API
Special elements
<script module>
Next steps
Basic SvelteKit
Introduction
Routing
Loading data
Headers and cookies
Shared modules
Forms
API routes
$app/state
Errors and redirects
Advanced SvelteKit
Hooks
Page options
Link options
Advanced routing
Advanced loading
Environment variables
Conclusion

これまで、状態の観点から反応性について説明してきました。しかし、それは物事のまだ半分( half of the equation )に過ぎません。状態は、何かがそれに 反応している場合 にのみ反応性があり、そうでない場合は単なる特殊な変数( sparkling variable )です。

反応するものは effect と呼ばれます。すでにエフェクト (状態の変化に応じて DOM を更新するために Svelte が作成するエフェクト) について説明しましたが、$effect ルーンを使用して独自のエフェクトを作成することもできます。

ほとんどの場合、$effect を使用するべきではありません。$effect は頻繁に使用するものではなく、困った時の最終手段として考えるのが最適です。たとえば、副作用( side effects )を イベント ハンドラー に配置できるのであれば、ほとんどの場合それが望ましいです。

setInterval を使用して、コンポーネントがマウントされている時間を追跡するとします。エフェクトを作成します。

App
<script>
	let elapsed = $state(0);
	let interval = $state(1000);

	$effect(() => {
		setInterval(() => {
			elapsed += 1;
		}, interval);
	});
</script>
<script lang="ts">
	let elapsed = $state(0);
	let interval = $state(1000);

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

speed upボタンを数回クリックすると、interval が小さくなるたびに setInterval が呼び出されるため、elapsed がより速く増加することがわかります。

次にslow downボタンをクリックしても、うまくいきません。これは、エフェクトの更新時に古い間隔をクリアしていないためです。クリーンアップ関数を返すことでこれを修正できます。

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

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

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

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

サーバー側のレンダリング中は$effectは実行されません。

Edit this page on 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>