How to use Svelte Keyed Each Block?
Tags: javascript, svelte, webdev
Published: 2022-01-18 12:28:08

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

In the normal  [Svelte Each Block](https://progressivewebninja.com/how-to-use-svelte-each-block-to-render-arrays/), 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`**
```js
<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>
```

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`**
```js
<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>
```

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](https://progressivewebninja.com/wp-content/uploads/2022/01/svelte-each-block-issue.png.webp)

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`**
```js
<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>
```

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.

```js
{#each books as book, idx (book.id)}
```


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](https://cdn.hashnode.com/res/hashnode/image/upload/v1642385377572/W9TmhfFzW.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.