Introduction to Svelte Derived Store

Introduction to Svelte Derived Store

In this article, we will learn how to make use of derived store from Svelte.

Introduction to Svelte Derived Store

We have already covered the Writable and Readable store in the previous articles. In this article, we will learn how to make use of derived store from Svelte. If you want a refresher on those topic, have a look at the following two topics

https://www.eternaldev.com/blog/introduction-to-svelte-stores/

https://www.eternaldev.com/blog/introduction-to-svelte-readable-store/

When to use Svelte derived store

When you want to perform on client side filtering based on user input, then using a derived store can be a good option. Store the actual data in the store and then use another derived store to store just the filtered options.

In general, if you want to derive another data from a store value and want that value to update every time the store updates, you can use derived store

Let’s skip these generic definition and see a practical example. We will implement a client side search on a list of post we have fetched.

What are we building today ?

SvelteDerivedPost.png

Building a home page which will have a list of post and then a search box to filter the post based on the search. We will pull the data from the Placeholder API which will return a total of 200 posts. When the user enter the text in the search box, we will use the derived store to filter the posts and show the filtered post to the user.

Create a derived store

Creating a derived store can be done after import derived from svelte/store. It needs to be dependent on either a writable or readable store and the value of this store is recalculated when one of its dependency changes

Create a new file called postStore.svelte inside the new folder called `store

import { writable, derived} from "svelte/store";
import type { Writable } from "svelte/store";

type Post = {
    title: string;
    body: string;
}

export const allPostStore: Writable<Post[]> = writable([]);
export const filteredText: Writable<string> = writable("");

export const filteredPostStore = derived([allPostStore, filteredText], ([$allPostStore, $filteredText]) => {
    return $allPostStore.filter((item) => item.title.includes($filteredText));
})

Let’s breakdown the above code

  1. We are importing the needed items from svelte/store
  2. We are creating a Post type which fits the response form the API (placeholder post API)
  3. Create allPostStore writable store which will be used to store the list of post from the API
  4. Create filteredText writable store which will store the value of the text entered in Search input text
  5. Finally, create the derived store, which will take the other two stores as dependencies as the first argument in array. Second argument is function which will have access to the dependent stores.
  6. Then we can filter the all post list and only include the post which contains the search text in the title.

Create a component to use derived store

Create a new file called PostDisplay.svelte and add the following code

<script lang="ts">
    import {onMount} from "svelte";
    import {allPostStore, filteredPostStore, filteredText} from '../store/postStore';

    let postPromise;
    
    onMount(() => {
        postPromise = fetch('https://jsonplaceholder.typicode.com/posts').then((data) => data.json()).then((post) => {
            $allPostStore = post;
        });
    })
</script>
  1. Import all the store from the ../store/postStore. This will give us access to the store to read and write content
  2. Add the onMount life cycle method which will be called on the component being rendered on the screen
  3. Call the Placeholder API to fetch a list of posts and then store the data in the $allPostStore store.

Now we have access to all the post. When the user enters the search text, we can do front-end filtering of the list and display only the post which match the search text. This is where our derived store helps.

We store the post value in the $allPostStore but we can use the derived store variable to display the post. This means that the original list of all the post is not disturbed and we get a new filtered list every time the search text changes. Sweet!

<h1>Posts</h1>

{#await postPromise}
    <h2>Loading....</h2>    
{:then post}

    <input type="text" placeholder="Search..." bind:value={$filteredText} name="search"/>

    <div class="post-container">
        {#each $filteredPostStore as post}
            <h3>{post.title}</h3>
            <p>{post.body}</p>
        {/each}
    </div>

{:catch error}
    <h3>Error while loading the data</h3>
{/await}
  1. We are using the await svelte syntax to make our life easier and then show the loading and error message.
  2. Input field value is being linked to $filteredText which is the store variable using bind:value. So it automatically updates the store value. Wow!
  3. Using the #each syntax, we can iterate through the derived store $filteredPostStore and display the post in a list

Final Result

Svelte Derived Post