Skip to content

Instantly share code, notes, and snippets.

@sagarpanchal
Last active February 15, 2024 12:38
Show Gist options
  • Save sagarpanchal/8dfa9ef65da0378efe710a3dc71bc3f9 to your computer and use it in GitHub Desktop.
Save sagarpanchal/8dfa9ef65da0378efe710a3dc71bc3f9 to your computer and use it in GitHub Desktop.
Zustand Usage Example
import { createStore } from "zustand"
import { subscribeWithSelector } from "zustand/middleware"
export function chain<T>(object: T) {
const call =
<V>(previousResult: V) =>
<U>(callback: (object: T, result: V) => U) => {
const result = callback(object, previousResult)
return { call: call(result), result: () => result, object: () => object }
}
return { call: call(undefined), result: () => undefined, object: () => object }
}
export class LoaderService {
static readonly store = createStore(subscribeWithSelector(() => 0))
private static subscriptions: (() => void)[] = []
static set count(n: number) {
LoaderService.store.setState(n)
}
static get count() {
return LoaderService.store.getState()
}
static get isLoading() {
return LoaderService.store.getState() > 0
}
static startLoading() {
this.count = chain(this.count)
.call((count) => (count < 1 ? 1 : count))
.result()
}
static stopLoading() {
this.count = chain(this.count)
.call((count) => (count < 0 ? 0 : count))
.result()
}
static adjustCount(count: number) {
LoaderService.store.setState(LoaderService.store.getState() + count)
}
public static init() {
LoaderService.dispose()
LoaderService.subscriptions = [
LoaderService.store.subscribe(
(count) => count,
(count, prevCount) => {
if (count < 0) LoaderService.store.setState(0)
switch (true) {
case count > prevCount:
console.info("Loading started")
break
case count < prevCount:
console.info("Loading stopped")
break
}
},
),
]
}
public static dispose() {
LoaderService.subscriptions.forEach((unsubscribe) => unsubscribe())
}
}
import { createStore, useStore } from "zustand";
import { subscribeWithSelector } from "zustand/middleware";
// store
export const store = createStore(
subscribeWithSelector(() => ({
loading: 0,
}))
);
// action to start loading
export const startLoading = () => {
store.setState({ loading: store.getState().loading + 1 });
};
// action to stop loading
export const stopLoading = () => {
store.setState({ loading: store.getState().loading - 1 });
};
// usage with react function component
export const ReactComponent = () => {
const isLoading = useStore((state) => state.loading > 0);
return <div>{isLoading}</div>;
};
// Subscription with selectors
const removeSubscription = store.subscribe(
(state) => state.loading,
(loading, prevLoading) => {
switch (true) {
case loading > prevLoading: {
console.log("loading started");
break;
}
case loading < prevLoading: {
console.log("loading stopped");
break;
}
}
},
{ fireImmediately: true }
);
// to stop listening to changes
removeSubscription();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment