Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Derived store returns incorrect value

I have a simple text input that looks like this

// App.svelte

<script>
  import { todo, todos, count, addTodo, error } from "./stores";
</script>

<div>
    <input type="text" bind:value={$todo.text} />
        {#if $error}
            <span class="error">{$error}</span>
        {/if}
    <button on:click={addTodo}>Add Todo</button>
<!-- show todo items -->
</div>

Everything is abstracted out neatly into a store which looks like this:

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

export const todo = writable({ text: "", completed: false });
export const todos = writable([{ text: "Learn Svelte", completed: false }]);

const formState = writable({ status: "idle" });

export const addTodo = () => {
  formState.set({ status: "submitted" });
  let _error = get(error);
  if (!_error) {
    let _todo = get(todo);
    todos.update((todos) => {
      todos.push(_todo);
      todo.update(() => ({ text: "", completed: false }));
      return todos;
    });
    formState.set({ status: "idle" });
  }
};

...

export const error = derived(todo, todo => {
  if (get(formState).status === "submitted") {
    if (!todo.text.trim()) {
      return "Please enter a task";
    } else if (todo.text.length < 3) {
      return "Todo must be at least 3 characters long";
    }
    return "";
  }
});

I’m sure there’s better ways to do form validation but the purpose of this example is
to play around with Svelte stores. I have created an error derived store that does some validation once the form is submitted by subscribing to the todo value. When I click the ‘Add Todo’ button initially, I get the correct error, but an empty todo is rendered (and apparently the error is undefined), then the form validation kicks in subsequently. Why is this?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Codesandbox – https://codesandbox.io/s/stupefied-chaplygin-vzvg7e

>Solution :

Your derived store is implemented incorrectly: It does not list all stores it depends on.

If you ever use get you are losing reactivity, so that can be a sign something is wrong. In this case the formState needs to be included, otherwise the store will not update if that state changes:

export const error = derived([todo, formState], ([$todo, $formState]) => {
  if ($formState.status === "submitted") {
    if (!$todo.text.trim()) {
      return "Please enter a task";
    } else if ($todo.text.length < 3) {
      return "Todo must be at least 3 characters long";
    }
    return "";
  }
});

(Would recommend the $ prefix convention to not shadow variables and indicate that something is a store value, rather than the store itself.)

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading