Svelte store value not seen after it is set?

139 views Asked by At

I'm kind of new to Svelte. I have a simple store defined as follows:

import { writable } from 'svelte/store';

export let store = writable({});

Then, in my main app component, I do the following:

<script>
  import {store} from './store.js'
    
  async function functionOne() {
    console.log("functionOne called")
  }
  
  function setStore() {
    $store = {foo: 'bar'}
    console.log(`Store is set, equals: ${JSON.stringify($store)}`)
    return true
  }
</script>

<main>
  {#await functionOne()}
    Loading...
  {:then _}
    {#if setStore()}
      {console.log(`We are inside the #if block with store=${JSON.stringify($store)}`)}
    {/if}
  {/await}
</main>

When I run this, I get the following log:

functionOne called
Store is set, equals: {"foo": "bar"}
We are inside the #if block with store={}
We are inside the #if block with store={"foo": "bar"}

What seems to be happening is:

  1. Svelte initializes the app, it calls the function in the #await block, and moves on to the :then clause.
  2. There, it finds an #if block and evaluates the condition. The condition sets the store (the result is logged in line 2).
  3. Svelte then moves over to the body of the #if block. Here the store is not set (!!!)
  4. Then, the body of the #if block runs again with the store value set

My question is: What is going on? If the store is set in step 2 (as we can see from the fact that its value is logged), why does Svelte execute the body of the #if block as if it wasn't in step 3?

REPL

3

There are 3 answers

1
codemt On

A better solution would be:

import { writable } from 'svelte/store';

export const emp_details = writable({
   emp_id:1,
   emp_name:'John Doe'
})

Now import this in your component and access it directly.

<script>
  import { emp_details } from '../store'
</script>
<div>
   <h3> The emp name is {$emp_details.emp_name} </h3> 
</div>

You can call methods like update to update value of the store.

emp_details.update((emp_details)=>{
  return {
      emp_id:5,
      emp_name:'John'
  }

})

Checkout this enter link description here for svelte store example.

0
brunnerh On

DOM updates are asynchronous, so changes may only be reflected in the next update cycle. In general you should avoid mutating state via functions in the markup, it is harder to reason about and does not play well with the asynchronous nature of the updates.

0
Yilmaz On

I think it is related to how reactivity works in Svelte. The initial log inside the block shows {} because at the moment of its evaluation, Svelte might not have detected the updated value of $store due to its reactivity mechanism. Subsequently, when Svelte re-renders the component (at thsi point it is aware the change in store), it correctly displays the updated value of $store in the subsequent log statement.