如何解决使用ImmerJS和Svelte不可变商店创建镜头,我缺少什么
我正在研究svelte和ImmerJS。
Immerjs和svelte商店应该能够以一种非常优雅的方式构成。
我试图仅使用选择器表达式从父存储创建派生可写存储,其中选择器表达式(从.NET借用的术语)是一个函数lambda,它描述了如何访问对象树的某些子部分。
root => root.a.b[10].foo
通常人们必须对此进行解析,但是我认为immerjs已经使用代理和Draft<T>
类完成了艰苦的工作。
因此,目的是能够执行以下操作。
import {writable} from "svelte/store"
import {lens} from "my_magic_lens_library_not_yet_written"
interface Foo {
a: number
b: string
}
interface Bar {
foo1: Foo
foo2: Foo
}
let bar:Bar = {
foo1: {a:10,b:"monkey"},foo2: {a:20,b:"cat"}
}
let barStore:Writable<Bar> = writable(bar)
let foo1_a_Store:Writable<number> = lens(barStore,(b:Draft<Bar>) => b.foo1.a)
barStore.subscribe(v=>console.log(v))
foo1_a_Store.set(77)
我希望输出是
{ foo1: { a: 10,b: 'monkey' },foo2: { a: 20,b: 'cat' } }
{ foo1: { a: 77,b: 'cat' } }
但是是
{ foo1: { a: 10,b: 'cat' } }
{ foo1: { a: 10,b: 'cat' } }
镜头的实现方式是
import {writable,Writable} from "svelte/store"
import {produce,Draft} from "immer"
type Updater<T> = (arg0:T)=>T
type Selector<T,U> = ((ar:T)=>U) & ((ar:Draft<T>)=>Draft<U>);
function lens<T,U>(store:Writable<T>,selector:Selector<T,U>):Writable<U>
{
let {subscribe,set,update} = store
function subSet(v:U):void
{
let rootUpdater = (oldValue:T) => {
return produce(
oldValue,(ds:Draft<T>) => {
let subDraft:Draft<U> = selector(ds)
Object.assign(subDraft,v)
}
)
}
update(rootUpdater)
}
function subUpdate(updater:Updater<U>):void
{
let rootUpdater = (oldValue:T) => {
return produce(
oldValue,(ds:Draft<T>) => {
let subDraft:Draft<U> = selector(ds)
Object.assign(subDraft,updater(selector(oldValue)))
}
)
}
update(rootUpdater)
}
return {
subscribe: subscriber => subscribe(v=>subscriber(selector(v))),set: subSet,update: subUpdate
}
}
我很确定失败的行是
Object.assign(subDraft,updater(selector(oldValue)))
在这里,我尝试将更新的值传播到子草稿中。谁知道这是否有可能?但这应该是。有人可以找出神奇的调味料来使它起作用吗?
repl.it上有一个实时版本
https://repl.it/@BradPhelan/Substore
解决方法
使用我写的名为immer-loves-svelte的新软件包来实现这一目标。导出了一个名为subStore
的函数,使您可以从父级创建子级存储
import {writable,Writable} from "svelte/store"
import {produce,Draft,isDraft} from "immer"
import {subStore} from "immer-loves-svelte"
interface Foo {
a: number
b: string
}
interface Bar {
foo1: Foo
foo2: Foo
}
let bar:Bar = {
foo1: {a:10,b:"monkey"},foo2: {a:20,b:"cat"}
}
let barStore:Writable<Bar> = writable(bar)
// magic happens at this line with subStore call
let foo1_a_Store:Writable<number> =
subStore(barStore,b => b.foo1.a)
barStore.subscribe(v=>console.log(v))
foo1_a_Store.set(77
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。