S
SolidJSā€¢14mo ago
subframe7536

how to`createStore` and using `createEffect` to persist without warning

I want to create a function to persist the store to the localstorage, everything works, but it warns that computations created outside a createRoot or render will never be disposed. I have tried to move createEffect outside onMounted, but it even warn twice. Additionally, moving onMounted inside provider makes persist break. No help using ChatGPTšŸ„². Does anyone know how to solve it? here is my code
export function persistStore< T extends object = {}, R extends ActionReturn = {}>(
name: string,
options: StoreOption<T, R>,
): [provider: ParentComponent, useStore: () => BaseStore<T, R>] {
const { action, state, persist: persistOption } = options
const initalState = typeof state === 'function' ? state() : state
const [store, setStore] = createStore<T>(initalState, { name })

const ctxData = { store, ...action(setStore) }
const ctx = createContext(ctxData, { name: `ctx_${name}` })
const option = normalizePersistOption(name, persistOption)
onMount(() => {
if (!option) {
return
}
const { debug, key, serializer: { deserialize, serialize }, storage } = option
const stored = storage.getItem(key)
try {
if (stored) {
setStore(deserialize(stored))
debug && console.log(`[$store - ${key}]: read from persisted, value: ${stored}`)
} else {
storage.setItem(option.key, serialize(store))
debug && console.log(`[$store - ${key}]: no persisted data, initialize`)
}
} catch (e) {
debug && console.error(`[$store - ${key}]: ${e}`)
}
createEffect(on(() => deepTrack(store), () => {
debug && console.log(`[$store - ${key}]: update to ${JSON.stringify(store)}`)
storage.setItem(option.key, serialize(unwrap(store)))
}))
})
return [
(props: ParentProps): JSX.Element =>
createComponent(ctx.Provider, {
value: ctxData,
get children() {
return props.children
},
}),
() => useContext(ctx),
]
}
export function persistStore< T extends object = {}, R extends ActionReturn = {}>(
name: string,
options: StoreOption<T, R>,
): [provider: ParentComponent, useStore: () => BaseStore<T, R>] {
const { action, state, persist: persistOption } = options
const initalState = typeof state === 'function' ? state() : state
const [store, setStore] = createStore<T>(initalState, { name })

const ctxData = { store, ...action(setStore) }
const ctx = createContext(ctxData, { name: `ctx_${name}` })
const option = normalizePersistOption(name, persistOption)
onMount(() => {
if (!option) {
return
}
const { debug, key, serializer: { deserialize, serialize }, storage } = option
const stored = storage.getItem(key)
try {
if (stored) {
setStore(deserialize(stored))
debug && console.log(`[$store - ${key}]: read from persisted, value: ${stored}`)
} else {
storage.setItem(option.key, serialize(store))
debug && console.log(`[$store - ${key}]: no persisted data, initialize`)
}
} catch (e) {
debug && console.error(`[$store - ${key}]: ${e}`)
}
createEffect(on(() => deepTrack(store), () => {
debug && console.log(`[$store - ${key}]: update to ${JSON.stringify(store)}`)
storage.setItem(option.key, serialize(unwrap(store)))
}))
})
return [
(props: ParentProps): JSX.Element =>
createComponent(ctx.Provider, {
value: ctxData,
get children() {
return props.children
},
}),
() => useContext(ctx),
]
}
1 Reply
subframe7536
subframe7536ā€¢14mo ago
well, I finally struggly solve it my self. According to https://github.com/solidjs-community/solid-primitives/blob/main/packages/context/src/index.ts, wrap onMount with a function and call it in createComponent, and all works without warn