DEV Community

Cover image for How to use Svelte Keyed Each Block?
Saurabh Dashora
Saurabh Dashora

Posted on • Updated on • Originally published at progressivewebninja.com

How to use Svelte Keyed Each Block?

In this post, we learn how to use Svelte Keyed Each Block.

In the normal Svelte Each Block, we use the each keyword to render an array or list. While it works perfectly when we have static lists, there is a serious issue when we delete items from the list. We are going to first look at the issue and then come up with the solution to it.

1 – Svelte Each Block Issue

To demonstrate the issue, we will take the example of displaying books and their respective authors.

Below is our App component.

App.svelte

<script>
    import Book from "./Book.svelte"

    let books = [{
        bookName: "Eye of the World",
    },
    {
        bookName: "The Way of Kings",
    },
    {
        bookName: "The Name of the Wind",
    }]

    function handleClick() {
        books = books.slice(1);
    }

</script>

<h1>Welcome to the Fantasy Library</h1>
{#each books as book, idx}
<h3>{idx + 1}</h3>
<Book 
    bookName = {book.bookName}
/>
{/each}
<button on:click={handleClick}>
    Remove first Book
</button>
Enter fullscreen mode Exit fullscreen mode

In the above piece of code, we have the books array with three hard-coded books. We use the each block to render the books using the Book component. Finally, we also have a button to remove the first book from the each block. When the user clicks the button, we invoke the handleClick() function that slices the books array.

Below is the code for the Book component.

Book.svelte

<script>
    const authors = {
        "Eye of the World": "Robert Jordan",
        "The Way of Kings": "Brandon Sanderson",
        "The Name of the Wind": "Patrick Rothfuss",
    }

    export let bookName;

    const author = authors[bookName];
</script>
<div>
    <span>Book Name: {bookName} // Author: {author}</span>
</div>
Enter fullscreen mode Exit fullscreen mode

In this component, we have the book to author map. Based on the input bookName, we basically determine the name of the author.

If we run the app now and then click the button to remove first book once, we will see the below output.

svelte-each-block-issue.png

As you can see, the bookName and the authorName does not match. Though the first book was correctly deleted, the authorName got mixed up.

Why does this happen?

The reason is that when we modify the underlying array of an each block, Svelte adds and removes items from the end of the block. It also updates any values that have changed. This is the default behaviour.

Due to this, the last item is removed and the items above it are updated. However, the author value is not updated because it is the local constant of the Book component. Its value was fixed at the time of component initialization. This leads to the data mismatch.

2 – The Svelte Keyed Each Block

To get around this issue, we need to use keyed each block.

See below example:

App.svelte

<script>
    import Book from "./Book.svelte"

    let books = [{
        id: 1,
        bookName: "Eye of the World",
    },
    {
        id: 2,
        bookName: "The Way of Kings",
    },
    {
        id: 3,
        bookName: "The Name of the Wind",
    }]

    function handleClick() {
    books = books.slice(1);
    }

</script>

<h1>Welcome to the Fantasy Library</h1>
{#each books as book, idx (book.id)}
<h3>{idx + 1}</h3>
<Book 
    bookName = {book.bookName}
/>
{/each}
<button on:click={handleClick}>
    Remove first Book
</button>
Enter fullscreen mode Exit fullscreen mode

Basically, here we introduce an id field in the books array. Each book has a unique id. In a real life application, this id could also be the database id. The point is that it should be unique for every item.

We also utilise this id in the each block as below.

{#each books as book, idx (book.id)}
Enter fullscreen mode Exit fullscreen mode

Basically, the role of this id field is to help Svelte figure out which DOM node should be changed when the each block updates. After this modification, if we run the application and click the button, we will see proper data as below.

svelte-keyed-each-block-fix.png

The book name and author name match as expected. The first book was successfully removed. However, Svelte only removed the appropriate DOM node and other nodes were left as they were before the update.

Conclusion

With this, we have learnt how to use Svelte Keyed Each Block. This is extremely useful when we have a requirement to update elements within our each blocks.

Hope this little post was useful. If you have any comments or queries about this post, please feel free to write them in the comments section below.

Discussion (0)