Svelte Custom Stores for React Developers: Part 2

This is part 2 of a walkthrough of me learning how to use custom data stores in Svelte. To see the initial setup, please read Part 1

Now that I have set up a Svelte custom data store, and then used that store to display a list of animal HTML representations of the data from a local API, I want to make sure that my store is truly maintaining its own state, and that it is available to multiple components.

Mini Animal List

I decided to create another component that create a list of animal HTML representations, but each one is very small, and uses a cute puppy emoji 🐶.

src/animals/MiniAnimalList.svelte

<script>
  import { animals, getAnimals } from "./AnimalStore.js";
  getAnimals()
</script>

<article class="animals">
  {#each $animals as animal}
    <section>🐶 { animal.name }</section>
  {/each}
</article>

Showing Both Lists

Now to update the main Kennel component to render both lists.

<main>
  <h1>Nashville Kennels</h1>

  <div class="splitScreen">
    <AnimalList />
    <AnimalMiniList />
  </div>
</main>

And after a the page auto-refreshes, here's what I see.

Screen-Shot-2020-08-02-at-3.07.39-PM

Reacting to Changes

Ok, so both components rendered their own HTML representatios of the data, but I have to do one more check to make sure that they both reference the same data and aren't working with their own copies of the array.

I decide to add a button to the main animal list component that, when clicked, performs a POST to the API to add a test animal. If this all works the way it's supposed to, the mini animal list should immediately re-render with the new animal.

POST Method in the Store

Time to add a function to the data store that will perform a POST fetch to create a new animal in the API.

src/animals/AnimalStore.js

... existing code ...

export const createAnimal = async (animal) => {
    const response = await fetch("http://localhost:8088/animals", {
        "method": "POST",
        "headers": {
            "Content-Type": "application/json"
        },
        "body": JSON.stringify(animal)
    });
    const new_animal = await response.json();

    if (response.ok) {
        await getAnimals()
    }
}

Creating Animals in the List

Now to update the animal list component with a simple test animal object, and a button for the user to click to initiate the entire process.

src/animals/AnimalList.svelte

<script>
  // Updated to import new `createAnimal()` function
  import { animals, getAnimals, createAnimal } from "./AnimalStore.js";
  getAnimals();

  // Simple animal object in component state
  const test_animal = {
    name: "Test",
    breed: "Jack Russell"
  };
</script>

<button on:click={() => createAnimal(test_animal)}>
  Create Test Animal
</button>

<article class="animals">
  {#each $animals as animal}
    <section class="animal">
      <div class="animal--name">
        <h2>{animal.name}</h2>
      </div>
      <div class="animal--breed">{animal.breed}</div>
    </section>
  {/each}
</article>

Ok, fingers crossed. Let's see if both components update immediately on state change.

svelte-shared-store-proof

It Works!

Well, that was pretty cool. Now both components are interacting with the same store and staying in sync whenever the data changes.

I hope you found this quick walkthrough helpful!