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

Svelte reactivity for data returned from a store

I’m wondering about a component and how its local variables that capture a computed result from a store, and how reactivity comes in.

If I have a store defined like so:

export const getInitialState = (): RoundState => ({
  playerNames: [],
  locked: false,
  finished: false,
  questions: [],
  picksChosen: false,
  roundPicks: [],
})

export const round = writable<RoundState>(getInitialState())
export const questions = derived(round, (round) => round.questions)

And then inside a component i want to use the questions array as a starting point, using it to create local form data:

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

<script lang="ts">
  import { onMount } from 'svelte'
  import {
    questions
  } from '../../lib/stores/round'

  function loadData() {
    // fetches data from an api that update's round store
    getRoundStatus()
  }

  let answers: Answers
  answers = $questions.map((q) => ({
    id: q.id,
    label: q.body,
    value: '',
  }))
</script>

{#each answers as answer}
  <select />
{/each}

My thinking is that because i’m using a local variable that assigns to the auto subscription, it should work: https://svelte.dev/docs#component-format-script-2-assignments-are-reactive. However in my test suite i’m finding this is not the case.

If i update it to be a reactive statement, it’s fine.

  let answers: Answers = $questions.map((q) => ({
    id: q.id,
    label: q.body,
    value: '',
  }))

However given the docs example i posted, I feel like this shouldn’t be needed. So my question here is if i’m doing something incorrect.

>Solution :

You are not assigning $questions, you are only reading it, and unless the reading happens in the template part of the component or a reactive statement, this will only happen once.

The result of the operation is not reactive in itself, so it will not be modified after that.


To illustrate the behavior of stores maybe more intuitively, consider the use within a function:

function do(a, b, c) {
  const value = a + $store;
  // ...
}

There would be no way for Svelte to just call the function again simply because the store changed as the required arguments may be unknown, it could cause unwanted side effects, etc.

It is best to think of the "auto-subscription" in the context of the script as a simple read operation. It does not cause re-evaluation by itself. Hence the requirement to use a reactive statement.

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