import create, { StoreApi } from "zustand"; import produce from "immer"; import { persist, subscribeWithSelector } from "zustand/middleware"; import { MMKV } from "react-native-mmkv"; import { name as appName } from "../app.json"; import deviceInfoModule from "react-native-device-info"; export type StoreState = { theme: "light" | "dark"; rehydrated: boolean; set: (fn: (state: StoreState) => void) => void; setStore: StoreApi["setState"]; }; export const MMKVStorage = new MMKV({ id: "main-mmkv-storage", encryptionKey: deviceInfoModule.getUniqueIdSync(), }); export const initialStore = { theme: "light", rehydrated: false, } as Omit; const getStorage = { getItem: (name: string) => MMKVStorage.getString(name) ?? null, setItem: (name: string, value: string) => MMKVStorage.set(name, value), removeItem: (name: string) => MMKVStorage.delete(name), }; export const useStore = create()( subscribeWithSelector( persist( (set) => ({ ...initialStore, set: (fn) => set(produce(fn)), setStore: set, }), { name: `${appName}-storage`, getStorage: () => getStorage, // do not persist rehydated state partialize: ({ rehydrated, ...rest }) => rest, onRehydrateStorage: () => async (state) => { // DO async stuff here before navigation mounts requestAnimationFrame(() => { state?.set((s) => { s.rehydrated = true; }); }); }, } ) ) ); export function useUpdateStore() { return useStore((store) => store.set); }