TECH_COMPARISON

Zustand vs Jotai: Centralized Store vs Atomic State in React

Zustand uses a single store with slice-based state; Jotai composes tiny atoms for fine-grained, component-colocated state management.

7 min readUpdated Jan 15, 2025
zustandjotaistate-managementreactatoms

Overview

Zustand and Jotai are the two most popular minimal state management libraries for React, and notably both were created by the same author — Daishi Kato. Despite sharing an author and a commitment to simplicity, they embody different state management models. Zustand is store-based: you create a store (or multiple stores) containing state slices and actions, and components subscribe to the store. Jotai is atomic: state is composed from tiny, independent atoms, and components subscribe to specific atoms.

Thinking about which to use often comes down to how you think about the shape of your state. If your state is naturally a coherent collection of values and operations (a user session, a shopping cart, a UI panel state), Zustand's store model fits well. If your state is a collection of independent values that happen to share an application scope (selected items, toggle states, fetched data), Jotai's atomic model fits well.

Key Technical Differences

Zustand's store is a closure that holds state and exposes getters and setters. It can be accessed from outside React via store.getState() and store.setState(), making it suitable for use in plain JavaScript services, event handlers, and WebSocket callbacks that live outside the React component tree. This outside-React access is a genuine advantage when your application has significant non-React code.

Jotai's atoms are React-first. The useAtom hook is the primary API, and atoms are designed to participate in React's lifecycle — atoms can be garbage collected when no components use them, enabling memory-efficient handling of large lists of atoms. Jotai's async atoms return a Promise and automatically integrate with React Suspense, enabling a clean async data access pattern without explicit loading state management.

Zustand's middleware system is straightforward: devtools, persist, immer, and subscribeWithSelector are composable wrappers applied at store creation. The persist middleware for Zustand is particularly clean — it handles localStorage serialization and hydration with minimal configuration. Jotai has jotai/utils with equivalents, but Zustand's middleware pattern is slightly more ergonomic for persisted state.

Performance & Scale

Both libraries achieve fine-grained subscriptions. Zustand's useStore(selector) only triggers re-renders when the selected slice changes. Jotai's useAtom only triggers re-renders when the specific atom value changes. At scale, both perform excellently. The 1KB vs 3KB bundle size difference is negligible for most applications but matters for bundle-budget-sensitive scenarios.

When to Choose Each

Choose Zustand when you have significant non-React code in your application that needs to read and update state, when your state is naturally store-shaped, or when you want the smallest possible footprint. Zustand's no-Provider requirement also simplifies testing.

Choose Jotai when your state is more atomic in nature, when you need Suspense-native async data, or when derived state composition is a primary concern. Jotai's atom model encourages fine-grained state decomposition that can lead to cleaner component boundaries.

Bottom Line

Both are excellent choices and both were built by the same author — choosing between them is more about state model preference than quality. Use Zustand if you think in stores; use Jotai if you think in atoms. For many projects, either works equally well.

GO DEEPER

Master this topic in our 12-week cohort

Our Advanced System Design cohort covers this and 11 other deep-dive topics with live sessions, assignments, and expert feedback.