In Svelte, when using a writable
store that takes a single primitive value (e.g. a string), when firing set
multiple times for the same value, subscribe
will only be called when the value changes. Demo in Svelte REPL
However, when storing a complex object, every time set
is called, even if the object has the same properties, subscribe will still be fired. Demo in Svelte REPL
I'm running a fairly expensive external API call on updates (handled via subscribe), so I want to limit if the data hasn't changed. How best should I prevent firing set or listening to subscribe if the data is the same as the previous run?
An attempt at a solution would be to keep the previous value inside a closure and compare before calling set and then carefully expose which API methods are available for consumers of the store like this:
import { writable, get } from "svelte/store";const initialContentState = { title: "", body: "",};const { subscribe, set } = writable(initialContentState);const isQuestionEqual = (a,b) => { return a.title === b.title && a.body === b.body;}const initQuestionContentStore = () => { let prevValue = initialContentState; return { subscribe, reset() { set(initialContentState) }, setContent(content) { if (!isQuestionEqual(content, prevValue)) { set(content); prevValue = content; } } }}export const questionContentStore = initQuestionContentStore()
Demo in Svelte REPL
However, feels weird to have to keep track of the state within the store which is supposed to be responsible for keeping track of state itself. I could also use get
to fetch the value from the store inside of the setContent
method, but docs suggest against it for perf reasons
Note: This is similar to Why does my Svelte store subscribe() get fired when the value hasn't changed?, but I want a workaround, not a reason.