-
-
Save dimfeld/0ff834a2fcd6f7bf575eeb21471c290e to your computer and use it in GitHub Desktop.
import { writable, Readable } from 'svelte/store'; | |
import { produce, enableAllPlugins } from 'immer'; | |
enableAllPlugins(); | |
export interface ImmerStore<T> { | |
update: (updateFn: (draft: T) => T | void) => T; | |
subscribe: Readable<T>['subscribe']; | |
} | |
export default function immerStore<T = any>(initialValue: T): ImmerStore<T> { | |
let store = writable<T>(initialValue); | |
let update = (updateFn: (draft: T) => T | void) => { | |
let ret; | |
store.update((value) => { | |
ret = produce(value, updateFn) as T; | |
return ret; | |
}); | |
return ret; | |
}; | |
return { | |
update, | |
subscribe: store.subscribe, | |
}; | |
} |
@opensas Here's a really contrived example, but should make it clear how it makes things easier when working with highly nested data:
https://svelte.dev/repl/a03de6f7c44b4b68b6e6c90598a3c72f?version=3.23.2
That's great, if I understand correctly you could do something pretty similar with the writable store, like
w.update((obj) => {
obj.a.b.c.d.push(newValue)
return obj
});
but in that case you would be mutating the original object.
Would that also work with the autosubscription method? I tried this:
$w.a.b.c.d.push(newValue)
$w = $w
and it works, but
$i.a.b.c.d.push(newValue)
$i = $i
silently fails
The idea behind Immer is to keep the objects immutable while retaining the convenience of mutable-style code. If you're ok with mutating then the version with the writable is fine, though I believe you would have to return { ...obj }
to make sure that update
sees that it actually changed.
As for this:
$i.a.b.c.d.push(newValue)
$i = $i
The immer store as written in the Gist doesn't expose a set method. You could add one. Generally the first line would not work though since once Immer starts using an object it throws an error if you mutate the object outside immer's produce function. That may only happen in development mode though.
The idea behind Immer is to keep the objects immutable while retaining the convenience of mutable-style code.
Yes, that's exactly what I have in mind. I wish it could be almost transparent to work with stores in an immutable way, that's why I asked about auto-subscription support. Also, getting rid of the $i = $i would be nice, it still brings visual noise to my eyes.
I think that if it gets polished, an immutable store would be a great addition to svelte's arsenal.
This seems really interesting, could you provide a working example showing the differences with a regular writable store?