sveltesvelte-store

Questions about using Svelte stores with tree-like nested object


How does one use Svelte store with tree-like nested object? From this answer:

Note: bindings only works when it's the same variable. That is, you can't put the bound variable in an intermediate variable, and have Svelte keep tracking this binding.

This, and my own testing, seems to imply that one cannot reactively update the nested store (update the store and have this update the state) from a script external to a Svelte component. As far as I can see, the only way to do it is to manually call store.update() in the script after making changes to the store. Is this correct?

I am looking to refactor my code: my main component's code is getting too unwieldy and I would like to introduce more components, and possibly keep state-updating functions in .js files out of components for reusability.

Some questions on performance:

  1. Would doing manual updates be less performant than what Svelte does automatically?
  2. My app needs to handle a pretty big nested store, with hundreds of branches. In the answer linked above, it is proposed to create a nested store, with branches wrapped in their own stores. Would having hundreds of (nested) stores significantly increase the memory footprint of the app compared to just using a single store?

Solution

  • As far as I can see, the only way to do it is to manually call store.update() in the script after making changes to the store. Is this correct?

    This is almost correct. update receives a function which is passed the current value and expects the next value. If you manage your state outside and then pass it into a store, call set.

    const myNewValue = doStuff(oldValue);
    store.set(myNewValue);
    

    vs

    store.update(oldValue => doStuff(oldValue));
    

    Modifying the store value directly (like storeValue.property = 1) won't trigger an update, you have to explicetely update the store for Svelte to invalidate the variables. I also suggest to wrap these manipulations with methods on the store, which will help you keeping track of what is updated from where when the code gets bigger.

    store.js:

    const _store = writable(initialValue);
    
    function doASpecificModification(foo) {
      _store.update(oldValue => { ... });
    }
    
    export const store = {
      subscribe: _store.subscribe,
      doASpecificModification
    };
    

    Would doing manual updates be less performant than what Svelte does automatically?

    If by "automatically" you mean the $store = newValue syntax: That is desugared to a store.set(newValue), so there if no difference. Moreoever, Svelte will only rerender the parts where you subscribe to the store, so performance shouldn't be an issue (also see next section).

    My app needs to handle a pretty big nested store, with hundreds of branches. In the answer linked above, it is proposed to create a nested store, with branches wrapped in their own stores. Would having hundreds of (nested) stores significantly increase the memory footprint of the app compared to just using a single store?

    Regarding performance: It's probably better to make the updates more granular, either by wrapping the branches in their own stores, or by having one big store but have the slices of the store selected in a way that they don't trigger an update if their part did not change (derived stores will help you there). If these branches are unrelated to each other, then I suggest splitting them up (also to avoid a big blob; I don't like that Redux-style-keep-everything-in-one-object). The memory footprint is not a factor here.