React State Management: Choosing Between Zustand and Jotai
React State Management: Zustand vs. Jotai
Date: 2025-10-22 08:30
Location: Chongqing
---
📢 Click to follow our WeChat account to receive timely technical insights!

React’s ecosystem offers a rich set of state management libraries — from Redux and Mobx to modern Hooks-powered options like Zustand and Jotai.
In React 18 & 19, choosing between Zustand and Jotai — both authored by the same developer — comes down to understanding their differences.
We’ll explore them across four key dimensions:
- Design Philosophy
- Learning Cost
- Principle Analysis
- Project Suitability
If you have additional experience or insights, feel free to share in the comments. 👏🏻👏🏻
---
I. Design Philosophy
Zustand — Top-down centralized thinking
Much like Redux, Zustand maintains a centralized store.
You can organize states into modules and extract what’s needed via selectors.
Jotai — Bottom-up atomic design
Jotai breaks state into independent atoms, similar to utility-first CSS frameworks like Tailwind CSS. States are small, composable units.
---
II. Learning Cost
When introducing a state library, consider the learning curve for your team:
Ease of use, complexity of concepts, and API design.
Both Zustand and Jotai are:
React Hooks-based and functional programming-oriented.
Typical usage involves two simple steps:
- Define global state
- Consume and update state in components
---
Zustand Usage Example
Step 1: Define the store
// src/store/useConfigStore.js
import { create } from "zustand";
const useConfigStore = create((set) => ({
theme: "light",
lang: "zh-CN",
setLang: (lang) => set({ lang }),
setTheme: (theme) => set({ theme }),
}));
export default useConfigStore;Step 2: Use store in a component
// src/components/ZustandComponent.jsx
import { Fragment } from "react";
import useConfigStore from "../store/useConfigStore";
export default function ZustandComponent() {
const { theme, lang, setLang, setTheme } = useConfigStore((state) => state);
return (
theme: {theme}
lang: {lang}
setLang(lang === "zh-CN" ? "en" : "zh-CN")}>
setLang
setTheme(theme === "light" ? "dark" : "light")}>
setTheme
);
}---
Jotai Usage Example
Step 1: Define atoms
// src/store/useConfigAtom.js
import { atom } from "jotai";
const themeAtom = atom("light");
const langAtom = atom("zh-CN");
export { themeAtom, langAtom };Step 2: Use atoms in a component
// src/components/JotaiComponent.jsx
import { useAtom } from "jotai";
import { themeAtom, langAtom } from "../store/useConfigAtom";
export default function JotaiComponent() {
const [theme, setTheme] = useAtom(themeAtom);
const [lang, setLang] = useAtom(langAtom);
return (
theme: {theme}
lang: {lang}
setTheme(theme === "light" ? "dark" : "light")}>
setTheme
setLang(lang === "zh-CN" ? "en" : "zh-CN")}>
setLang
);
}📌 Observation: Both are easy to use, with minimal mental load.
---
Documentation Links:
---
III. Principle Analysis
Both libraries implement data-driven component re-rendering using the Observer Pattern via `subscribe`.
Zustand Internals
- Uses `useSyncExternalStore` from React 18 to subscribe components to external store updates.
- Store updates trigger component re-renders.
Conceptual Example:
import { useSyncExternalStore } from "react";
function create(createState) {
const store = {
state: undefined,
listeners: new Set(),
subscribe: (listener) => {
store.listeners.add(listener);
return () => store.listeners.delete(listener);
},
};
const setState = (partial, replace) => {
const { state, listeners } = store;
const nextState = typeof partial === "function" ? partial(state) : partial;
if (!Object.is(nextState, state)) {
const previousState = state;
store.state = replace ? nextState : { ...state, ...nextState };
listeners.forEach((l) => l(store.state, previousState));
}
};
store.state = createState(setState);
return function useStore(selector) {
return useSyncExternalStore(store.subscribe, () => selector(store.state));
};
}---
Jotai Internals
- Similar subscription model.
- Difference: Uses `useReducer` instead of `useSyncExternalStore` to force re-renders.
Conceptual Example:
import { useReducer, useEffect } from "react";
function atom(initialState) {
const config = {
state: initialState,
listeners: new Set(),
subscribe: (listener) => {
config.listeners.add(listener);
return () => config.listeners.delete(listener);
},
setState: (partial) => {
const nextState =
typeof partial === "function" ? partial(config.state) : partial;
if (!Object.is(nextState, config.state)) {
const previousState = config.state;
config.state = nextState;
config.listeners.forEach((l) => l(config.state, previousState));
}
},
};
return config;
}
export function useAtomValue(atom) {
const [[value], dispatch] = useReducer(
(prev) => {
const nextValue = atom.state;
if (Object.is(prev[0], nextValue)) return prev;
return [nextValue];
},
undefined,
() => [atom.state]
);
useEffect(() => {
const unsubscribe = atom.subscribe(dispatch);
return unsubscribe;
}, [atom]);
return value;
}
export function useSetAtom(atom) {
return atom.setState;
}
export function useAtom(atom) {
return [useAtomValue(atom), useSetAtom(atom)];
}---
IV. Project Suitability
Choosing between Zustand and Jotai depends mainly on design philosophy, not performance or ease of use.
- Choose Zustand if your team prefers Redux-like centralized store management, ideal for large-scale projects.
- Choose Jotai if you favor independent, composable state units, great for smaller or modular projects.
📌 Recommendation: Select based on your team’s workflow and project architecture.
---
Conclusion
Both Zustand and Jotai are simple, powerful, and modern state management solutions built for React Hooks.

---
💡 Tip for Content Creators
If you plan to share code tutorials or technical blogs across multiple platforms, consider AiToEarn — an open-source, AI-powered, global content monetization platform.
It supports cross-platform publishing to Douyin, Kwai, WeChat, Bilibili, Xiaohongshu, Facebook, Instagram, LinkedIn, Threads, YouTube, Pinterest, and X (Twitter), with built-in analytics and performance tracking.
Docs: AiToEarn文档 · Repo: GitHub
---
Would you like me to add a side-by-side comparison table for Zustand vs. Jotai in this article to make evaluation even faster? That would make this guide more actionable.