React State Management: Choosing Between Zustand and Jotai

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!

image

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

ZustandTop-down centralized thinking

Much like Redux, Zustand maintains a centralized store.

You can organize states into modules and extract what’s needed via selectors.

JotaiBottom-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.

image

Read Original

Open in WeChat

---

💡 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.

Read more