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

デフォルトでは、each ブロックの値を変更すると、ブロックの 末尾 に DOM ノードが追加・削除され、変更された値が更新されます。これはあなたが期待した動作ではないかもしれません。

説明するより見ていただいたほうがおわかり頂けるでしょう。Thing.svelte の中を見てみると、name は動的な prop ですが emoji は定数です。

‘Remove first thing’ ボタンを何回かクリックすると、以下のことが発生します:

  1. 一番最後のコンポーネントが削除される
  2. 残りの DOM ノードの name の値が更新されるが、絵文字は更新されない

もしあなたが React を経験しているなら、奇妙に見えるかもしれません。なぜなら、あなたは state が変更されたらコンポーネント全体が再レンダリングされることに慣れているからです。Svelte の動作は異なります: コンポーネントは一度だけ実行され、その後の更新は ‘きめ細やかに(fine-grained)’ 行われます。これにより、より高速に、よりコントロールしやすくなります。

これを修正する方法の1つとしては、emoji$derived の値にすることが考えられます。しかし、末尾の <Thing> コンポーネントを削除して全てを更新するより、先頭の <Thing> コンポーネントを完全に削除するほうが、理にかなっています。

そのためには、each ブロックの each イテレーションに一意な key を指定します。

App
{#each things as thing (thing.id)}
	<Thing name={thing.name}/>
{/each}

Svelte は内部的に Map を使用しているので、どんなオブジェクトでもキーとして使用できます。つまり (thing.id) の代わりに (thing) を使うことができます。しかし、文字列または数値を使用する方が一般的に安全です。なぜなら、例えばAPIサーバーからの新しいデータで更新する場合に、参照が等しくなくても同一性が持続することを意味するからです。

Edit this page on GitHub

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script>
	import Thing from './Thing.svelte';
 
	let things = $state([
		{ id: 1, name: 'apple' },
		{ id: 2, name: 'banana' },
		{ id: 3, name: 'carrot' },
		{ id: 4, name: 'doughnut' },
		{ id: 5, name: 'egg' }
	]);
</script>
 
<button onclick={() => things.shift()}>
	Remove first thing
</button>
 
{#each things as thing}
	<Thing name={thing.name} />
{/each}