Choosing Between Zustand and Jotai: Which React State Library Fits Your Project?
This article examines the design philosophies, learning curves, underlying principles, and project suitability of the React state management libraries Zustand and Jotai, providing code examples, implementation details, and guidance on selecting the appropriate tool based on team preferences and project scale.
Reacthas evolved with many state libraries, from early Redux and Mobx to modern Hook‑based solutions like Zustand and Jotai.
In React 18/19 projects, how should we evaluate and use the open‑source Zustand and Jotai libraries?
This article explores their design philosophy, learning cost, underlying principles, and project suitability.
1. Design Philosophy
Zustand : “top‑down centralized store”. Similar to Redux, it uses a single store with selector to retrieve parts of the state.
Jotai : “bottom‑up atomic design”. Inspired by Tailwind CSS, it splits state into independent atoms that can be composed.
2. Learning Cost
Both libraries are built on React Hooks functional programming. Usage requires two steps: define a global state and consume/update it inside components.
Zustand example
Define the store
import { create } from "zustand";
const useConfigStore = create((set) => ({
theme: "light",
lang: "zh-CN",
setLang: (lang) => set({ lang }),
setTheme: (theme) => set({ theme })
}));
export default useConfigStore;Consume and update state in a component
import { Fragment } from "react";
import useConfigStore from "../store/useConfigStore";
export default function ZustandComponent() {
const { theme, lang, setLang, setTheme } = useConfigStore(state => state);
return (
<>
<div>theme: {theme}</div>
<div>lang: {lang}</div>
<button onClick={() => setLang(lang === "zh-CN" ? "en" : "zh-CN")}>setLang</button>
<button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>setTheme</button>
</>
);
}Jotai example
Define atoms
import { atom } from "jotai";
const themeAtom = atom("light");
const langAtom = atom("zh-CN");
export { themeAtom, langAtom };Consume and update atoms in a component
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 (
<div>
<div>theme: {theme}</div>
<div>lang: {lang}</div>
<button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>setTheme</button>
<button onClick={() => setLang(lang === "zh-CN" ? "en" : "zh-CN")}>setLang</button>
</div>
);
}3. Principle Analysis
Both libraries trigger component re‑render via an observer pattern using subscribe mechanisms.
Zustand leverages React 18’s useSyncExternalStore hook to connect an external store and subscribe to its updates.
PS: If you are unfamiliar with useSyncExternalStore , refer to the React documentation: https://zh-hans.react.dev/reference/react/useSyncExternalStore
A simplified implementation creates a store with state and listeners, provides a setState function, and returns a useStore hook that calls useSyncExternalStore.
Jotai implements a similar pattern but uses useReducer instead of useSyncExternalStore to trigger updates.
In both cases the goal is to notify subscribed components after state changes.
4. Project Suitability
Both integrate similarly with React, and both are easy to use. Choose based on design philosophy: teams accustomed to Redux‑style centralized stores may prefer Zustand, while teams favoring atomic, composable state may find Jotai more flexible, especially for smaller projects.
Conclusion
Thanks for reading; feel free to share your insights.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
