Prompt
Create a Zustand store for a simple counter with increment and decrement actions. Persist the state to AsyncStorage using zustand/middleware.
Solution
Zustand's pitch is state outside the React tree: the store is a plain closure, components subscribe via the hook, and — the part worth saying in an interview — selectors like useStore(s => s.count) mean a component re-renders only when its selected slice changes, not on every store write. No Provider, no context cascade, actions colocated with state.
The persistence layering is the RN-specific knowledge: persist serializes state on change and rehydrates on startup, and createJSONStorage(() => AsyncStorage) adapts AsyncStorage's promise-based, string-only API to the middleware. Because AsyncStorage is async, rehydration is not instantaneous — the store starts at count: 0 and the persisted value arrives a tick later. Production code gates on onRehydrateStorage / hasHydrated to avoid flashing defaults or overwriting saved state. Also reach for partialize to persist only what should survive a restart — persisting everything is how transient UI state gets fossilized.
The security boundary matters most: AsyncStorage is plaintext. Persisting a counter is fine; persisting tokens or PII through this middleware ships secrets to unencrypted storage.
Red flag: persisting auth tokens via zustand-persist-to-AsyncStorage. Sensitivity decides the storage tier — secrets go to Keychain/Keystore-backed storage, never a persisted store.
Say it: "Zustand keeps state outside the tree with selector-scoped re-renders; persist plus a JSON storage adapter handles AsyncStorage — but rehydration is async and the store is plaintext, so I gate on hydration and never persist secrets."