I don't know if the title is super accurate, couldn't think of a better way to explain it.
Let's say we have a model:
let model = [
{
"id": 0,
"title": "Apple"
},
{
"id": 1,
"title": "Orange"
},
{
"id": 2,
"title": "Tomato"
},
{
"id": 3,
"title": "Avocado"
}
]
That we render like this:
{#each model as item}
<Item {...item}></Item>
{/each}
In the Item
component we print to console when the component gets mounted and destroyed:
<script>
import {onMount, onDestroy} from 'svelte'
export let id
export let title
onMount(() => {
console.log('Mounted: ' title)
})
onDestroy(() => {
console.log('Destroyed: ' title)
})
</script>
<div id={id}>{title}</div>
We also have a button, which deletes the "Orange" element from the model:
function deleteOrange() {
model.splice(1, 1)
model = model // I don't know if this is the correct way to force an update
}
// ...
<input on:click={deleteOrange} type="button" value="Delete Orange">
When the button is pressed, the Orange component disappears from the DOM as it should, but the console says:
"Destroyed: Avocado"
Is there a way to tell Svelte to destroy the "Orange" component, instead of destroying "Avocado" and moving props around to match the model?
Svelte REPL:
https://svelte.dev/repl/f22b37cb88c449118ff76bb5a82c296e?version=3.48.0
CodePudding user response:
Simply add a (key)
to your each
loop:
{#each model as item (item.id)}
<Item {...item}></Item>
{/each}
This will ensure that DOM elements are properly tracked. As per the Svelte documentation:
If a key expression is provided — which must uniquely identify each list item — Svelte will use it to diff the list when data changes, rather than adding or removing items at the end. The key can be any object, but strings and numbers are recommended since they allow identity to persist when the objects themselves change.