A cart that empties whenever Android kills the app in the background loses sales. Zustand 58,763 's persist middleware saves the state after every change and restores it at startup:
{
name: 'booknest-cart', // the AsyncStorage key
storage: createJSONStorage(() => AsyncStorage),
partialize: (s) => ({ items: s.items }), // save data, not functions
onRehydrateStorage: () => (s) => console.log('cart restored:', JSON.stringify(s?.items)),
},createJSONStorage adapts any storage with getItem/setItem/removeItem (AsyncStorage 5,070 here; MMKV 18,748 and expo-sqlite 6,418 's key-value store in Storage and Native Modules fit too) and serializes with JSON. partialize chooses what to save. After adding two copies of book 3, force-stopping BookNest and starting it again logged:
LOG cart restored: {"3":2}
...
LOG query cache restored
LOG catalog: 60 books, status success, fetch idleThe last two lines come from TanStack Query 79,069 's persister (Offline Persistence). Restoring is asynchronous, so the first render sees an empty cart; useCart.persist.hasHydrated() tells you when it's done. When the shape of the state changes in a later release, give the options a version number and a migrate function, or old saved state will be merged into the new shape as it is. Never persist secrets this way: AsyncStorage is plain, unencrypted storage (Secure Storage for Secrets covers the secure alternative).