gpt4 book ai didi

local-storage - 将 Svelte 存储持久保存到 localStorage

转载 作者:行者123 更新时间:2023-12-02 18:15:31 26 4
gpt4 key购买 nike

我有一个使用 Svelte(带有 Astro 的 SSR)的应用,并且我正在尝试将我的数据保存到 localStorage

关于这个 IMO 的文档还不够,因为我似乎经常遇到砖墙。

到目前为止我已经定义了这个商店:

import { writable } from 'svelte/store'

function createCart() {
const { subscribe, set, update } = writable([]);
return {
subscribe,
update: (item) => update(value => [...value, item]),
remove: (item) => update(n => {
if(n.length > 0) n.pop() // only remove last item
return n // update the store value
}),
empty: () => set([])
};
}

export const cart = createCart()

为了保存到localStorage(并且不会弄乱我的SSR),我已经实现了这个:

import { writable } from 'svelte/store'

function createCart() {

const defaultCartValue = []
const isClient = typeof window !== 'undefined'
const initialValue = isClient ? window.localStorage.getItem('cart') : defaultCartValue;

const { subscribe, set, update } = writable(
isClient
? window.localStorage.setItem('cart', initialValue)
: defaultCartValue
);
return {
subscribe: subscribe(value => localStorage.setItem('cart', ([
value,
...initialValue
]))),
update: (value) => isClient
? window.localStorage.setItem(
'cart',
JSON.stringify([...value, item])
)
: update(value => [...value, item]),
// TODO: fix remove items from localStorage
remove: (item => update(n => {
if(n.length > 0) n.pop()
return n
})
),
empty: () => isClient
? window.localStorage.setItem('cart', defaultCartValue)
: set(defaultCartValue)
};
}

export const cart = createCart()

我不断收到无法读取未定义的属性“取消订阅”,然后是stop不是一个函数

任何人都可以帮助我理解为什么我可能会看到这两个错误吗?

最佳答案

您收到的错误:

Cannot read property 'unsubscribe' of undefined followed by stop is not a function.

那是因为 subscribe商店的方法必须返回unsubscribe (又名 stop )函数。文档中并没有过多强调这一点,但它显示在方法的签名中:

subscribe: (subscription: (value: any) => void) => (() => void)

但是您自己的代码并没有做到这一点,而且,就其值(value)而言,它可能并没有真正实现您的预​​期:

        subscribe: subscribe(value => localStorage.setItem('cart', ([
value,
...initialValue
]))),

您正在调用原始 subscribe创建商店时立即,而不是注册新订阅者时。自原创subscribe确实返回 unsubscribe函数,您在尝试订阅时不会收到“不是函数”错误。但您也没有获得订阅,并且 unsubscribe函数不返回另一个函数,这解释了您所看到的错误。

你想要的是这样的:

subscribe: subscriber => {
// do something on every new subscriber

// subscribing
const unsubscribe = originalSubscribe(value => {
// do something every time the value change FOR EVERY SUBSCRIBER

subscriber(value) // notify the subscriber of the new value
}

// custom unsubscribe function
return () => {
// do something each time a subscriber unsubscribes

unsubcribe() // unsubscribe from the original store
}
}

如果您遵循上一个片段中的注释,您应该意识到包装 subscribe可能不是你想要坚持的localStorage ,因为通过这种方式获得的“ Hook ”适用于每个订阅者,而不是每个商店一次。


实现您想要的效果的一种方法是覆盖 setupdate可写存储的方法,如 svelte-local-storage-store does :

    const {subscribe, set} = store

stores[key] = {
set(value: T) {
updateStorage(key, value)
set(value)
},
update(updater: Updater<T>) {
const value = updater(get(store))

updateStorage(key, value)
set(value)
},
subscribe
}

另一种极其简单且方便的模块化方法就是订阅您的商店。

// a guard because we only want this in the clients
if (!isSSR() && typeof localStorage !== 'undefined') {
originalStore.subscribe(value => {
localStorage.setItem('key', JSON.stringify(value))
})
}

这仅适用于您不介意让您的商店“始终处于事件状态”的情况;也就是说,您可能不希望对“丰富”的商店执行此操作,例如,它在获得第一个订阅者时会发出请求。


利用原始商店 subscribe 的另一种方式在避免急切订阅它的陷阱的同时,将上述逻辑包装在可读的存储中。

const createPersistedStore = initialValue => {
const internal = writable(initialValue)

const persisting = readable(initialValue, set => {
// called when the store becomes active (i.e. first subscriber arrives)

const unsubscribe = internal.subscribe(value => {

updateLocalStorage(value) // <== will see each change once

set(value)
})

return () => {
// called when the store becomes inactive (i.e. last subscriber leaves)
unsubscribe()
}
})

return {
set: internal.set,
update: internal.update,
subscribe: persisting.subscribe,
}
}

关于local-storage - 将 Svelte 存储持久保存到 localStorage,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71639868/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com