Home > OS >  Why does my Svelte store subscribe() get fired when the value hasn't changed?
Why does my Svelte store subscribe() get fired when the value hasn't changed?

Time:12-16

I have a Svelte store activeAccountIndexStore:

export const activeAccountIndexStore: Writable<number | "native" | null> =
  writable(null);

The original value is null but after some network activity it will be set to a specific number or the string 'native'.

I also have a subscribe() handler for the store, that is called from other Svelte components:

export const onChangeActiveAccount = (
  activeAccountHandler: ActiveAccountHandler
) => {
  activeAccountIndexStore.subscribe((newValue) => {
    log(`➡️➡️➡️➡️➡️ activeAccountIndexStore new value`, newValue);
    if (newValue !== null) {
      const activeAccount = getActiveAccount();
      activeAccountHandler(activeAccount);
    }
  });
};

The odd thing is, the subscribe() change handler is being called repeatedly, even though the store has the same value in subsequent changes:

stores.ts:68 ➡️➡️➡️➡️➡️ activeAccountIndexStore new value null
stores.ts:68 ➡️➡️➡️➡️➡️ activeAccountIndexStore new value null
2stores.ts:68 ➡️➡️➡️➡️➡️ activeAccountIndexStore new value 0
stores.ts:68 ➡️➡️➡️➡️➡️ activeAccountIndexStore new value 0
stores.ts:68 ➡️➡️➡️➡️➡️ activeAccountIndexStore new value 0
stores.ts:68 ➡️➡️➡️➡️➡️ activeAccountIndexStore new value 0
stores.ts:68 ➡️➡️➡️➡️➡️ activeAccountIndexStore new value 0

MDNs Svelte docs state:

A store is an object with a subscribe() method that allows interested parties to be notified whenever the store value changes.

But the value is not changing in many of the cases above. I would have expected to see:

stores.ts:68 ➡️➡️➡️➡️➡️ activeAccountIndexStore new value null
stores.ts:68 ➡️➡️➡️➡️➡️ activeAccountIndexStore new value 0

Why does my Svelte store subscribe() get fired when the value hasn't changed?

CodePudding user response:

It has to do with re-evaluation of your Svelte components. If you're subscribing to a store inside a component, and instances of the component are being created and destroyed, the subscribe event will fire because the value is new for this instance of the component.

Re-evaluation of the component could happen if it gets unmounted, and re-mounted, or if the component is receiving new state.

A simple solution for this is to memoize the component state, eg do the .subscribe() outside of the component.

  • Related