Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Svelte store assignment calls default writable().set and then custom .set?

Relevant REPL

I have a simple writable store with a custom set method:

import { writable } from 'svelte/store';
function createState() {
    const {subscribe, set, update} = writable({a: 0, b: 0});
    return {
        subscribe,
        set: (newState) => {
            console.log(newState);
            // set(newState); // I would expect `state` to be unchanged without this
        }
    };
};

export const state = createState();

When I call state.set(<some new value>), the new value is logged to the console and the value of state does not actually change. This is what I expect.
However, if I assign $state = <some new value>, the value of state changes, and then set logs it to the console. Why (and how) does this happen, and is there a way around it without reimplementing writable?

Thanks!

like image 856
John LaRocque Avatar asked Jul 22 '20 06:07

John LaRocque


People also ask

What is writable in svelte?

It's a writable store, which means it has set and update methods in addition to subscribe . Now go to the Incrementer.svelte tab so that we can wire up the + button: function increment() { count. update(n => n + 1); } Clicking the + button should now update the count.

How do you persist shop in svelte?

In order to make the store persistent, just include the function useLocalStorage to the store object. // store.

How does svelte store work?

Svelte stores offer similar features for state management. A store is an object with a subscribe() method that allows interested parties to be notified whenever the store value changes, and an optional set() method that allows you to set new values for the store. This minimal API is known as the store contract.


1 Answers

This is expected behaviour! Forget about stores for a moment, and — since state.set is a noop in your example — remove that line:

<script>
    // import { state } from "./stores.js";

    let pojo = { a: 0, b: 0 };
    pojo.a = 1;
    pojo = {d: 0};

    //state.set({c: 0}); // no effect, as expected
</script>

<h1>state: {JSON.stringify(pojo)}</h1> 

The outcome...

state: {"d":0}

...is exactly what you'd expect.

When we replace pojo with $state, we're still assigning to (or mutating) a local variable, with the same reactivity characteristics. The only difference is that we're also calling state.set. Ordinarily that would cause a change in the store value that would be reflected to its subscribers, but since your custom store doesn't do that, we're left with the value following the last time $state was touched by an assignment operator.

like image 58
Rich Harris Avatar answered Sep 18 '22 10:09

Rich Harris