Support for Async Listeners
theskinnycoder opened this issue · 2 comments
We started using this library at work, and we were wondering if it is possible to add subscriptions to the whole store or a specific state variable. Maybe something like this :
const { use: useCounter } = defineModule({ count: 0 })
.actions({
add: (draft) => draft.count++,
minus: (draft) => draft.count--,
})
.computed({
doubled: (state) => state.count * 2,
})
.listen(async (store) => {
await fetch("/api/put-request", {
method: "PUT",
body: {
data: store
}
})
})
.build();
Thank you for your suggestion! I'm working on the new api for v0.5.0. Hope it will come out today😄
Currently, maybe you can use computed as a workaround
Hi @theskinnycoder
A new version is released with subscribe
support!
We can now trigger network requests on property change.
The sample code is like
const module = defineModule({ pokemonIndex: 0, input: '' })
.subscribe((state, prevState) => console.log(state)) // subscribe to the whole store
.subscribe({
selector: (state) => state.pokemonIndex, // only subscribe to some property
listener: async ({ pokemonIndex }, prev, { addCleanup }) => {
const abortController = new AbortController();
const abortSignal = abortController.signal;
addCleanup(() => abortController.abort()); // if you want to abort the previous promise, like switchMap in rxjs
const response = await fetch(`https://pokeapi.co/api/v2/pokemon/${pokemonIndex}`, { signal: abortSignal });
console.log(await response.json());
},
})
.build();
But there is some limitation, because module are globally initialized, zoov
will never destroy a module or unsubscribe
the listeners.
If you want to get better control over subscription lifecycle, you can call the original zustand
subscribe API, and unsubscribe it on demand.
The zustand store can be retrieved via module.getStore()
or module.useStore()
const store = module.useStore()
useEffect(() => {
const unsubscribe = store.subscribe(() => {});
return unsubscribe;
}, [])