Skip to content

Instantly share code, notes, and snippets.

@leosh1d
Created December 23, 2022 22:17
Show Gist options
  • Save leosh1d/abccc1ab352126c667a49c2e0c9d9a6c to your computer and use it in GitHub Desktop.
Save leosh1d/abccc1ab352126c667a49c2e0c9d9a6c to your computer and use it in GitHub Desktop.
Zustand (^4.1.5) persist middleware with deferred hydration.
import { persist, PersistOptions } from "zustand/middleware"
import { StateCreator, StoreApi, StoreMutatorIdentifier } from "zustand/vanilla"
type DeferredPersistOptions<S extends object> = PersistOptions<S> & {
hydrateOnResolve?: Promise<void>
}
const DEFAULT_GET_STORAGE = () => localStorage
export default function deferredPersist<
S extends object,
CustomSetState extends [StoreMutatorIdentifier, unknown][] = [
StoreMutatorIdentifier,
unknown
][],
CustomGetState extends [StoreMutatorIdentifier, unknown][] = [
StoreMutatorIdentifier,
unknown
][]
>(
config: StateCreator<
S,
[...CustomSetState, ["zustand/persist", unknown]],
CustomGetState,
S
>,
deferredOptions: DeferredPersistOptions<S>
) {
const hydrateOnResolve = deferredOptions.hydrateOnResolve || Promise.resolve()
const getStorage = deferredOptions.getStorage || DEFAULT_GET_STORAGE
const options: PersistOptions<S> = {
...deferredOptions,
getStorage: () => ({
setItem: async (...args) =>
hydrateOnResolve.then(() => getStorage().setItem(...args)),
getItem: async (...args) =>
hydrateOnResolve.then(() => getStorage().getItem(...args)),
removeItem: async (...args) =>
hydrateOnResolve.then(() => getStorage().removeItem?.(...args)),
}),
}
return persist<S, CustomSetState, CustomGetState>(config, options)
}
@tomtobac
Copy link

hey @leosh1d, thank you so much! It works perfectly 🙇

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment