State Management in 2025: Zustand vs Jotai vs Redux Toolkit

Compare modern React state management libraries. Zustand offers simplicity, Jotai provides atomic updates, and Redux Toolkit delivers enterprise-grade...

Y
Yash Pritwani
13 min read

The State of State Management

React's built-in state (useState, useReducer, useContext) works for simple apps, but medium-to-large applications need dedicated state management. In 2025, three libraries dominate: Zustand, Jotai, and Redux Toolkit.

InputHiddenHiddenOutput

Neural network architecture: data flows through input, hidden, and output layers.

Zustand: Simple and Powerful

Zustand (German for "state") is a small, fast state management library with a hook-based API. No providers, no boilerplate.

Setup

npm install zustand

Creating a Store

// stores/useAuthStore.ts
import { create } from "zustand";
import { persist } from "zustand/middleware";

interface User {
  id
  name
  email
}

interface AuthState {
  user: User | null;
  token | null;
  isAuthenticated: boolean;
  login: (email, password) => Promise<void>;
  logout: () => void;
}

export const useAuthStore = create<AuthState>()(
  persist(
    (set) => ({
      user: null,
      token: null,
      isAuthenticated: false,

      login: async (email, password) => {
        const response = await fetch("/api/login", {
          method: "POST",
          body: JSON.stringify({ email, password }),
          headers: { "Content-Type": "application/json" },
        });
        const data = await response.json();
        set({
          user: data.user,
          token: data.token,
          isAuthenticated: true,
        });
      },

      logout: () => {
        set({ user: null, token: null, isAuthenticated: false });
      },
    }),
    { name: "auth-storage" }
  )
);

Using the Store

Get more insights on Tutorials

Join 2,000+ engineers who get our weekly deep-dives. No spam, unsubscribe anytime.

// components/Header.tsx
function Header() {
  const { user, isAuthenticated, logout } = useAuthStore();

  if (!isAuthenticated) return <LoginButton />;

  return (
    <header>
      <span>Welcome, {user?.name}</span>
      <button 
    </header>
  );
}

// Only re-renders when user changes (selector)
function UserName() {
  const name = useAuthStore((state) => state.user?.name);
  return <span>{name}</span>;
}

Advanced: Slices Pattern

// Split large stores into slices
interface CartSlice {
  items: CartItem[];
  addItem: (item: CartItem) => void;
  removeItem: (id) => void;
  total: () => number;
}

interface UISlice {
  sidebarOpen: boolean;
  theme: "light" | "dark";
  toggleSidebar: () => void;
  setTheme: (theme: "light" | "dark") => void;
}

// Combine slices
export const useStore = create<CartSlice & UISlice>()((...a) => ({
  ...createCartSlice(...a),
  ...createUISlice(...a),
}));

Jotai: Atomic State

Jotai (Japanese for "state") uses atoms — tiny independent pieces of state that can be composed. It is React-centric and works with Suspense.

Setup

npm install jotai
PromptEmbed[0.2, 0.8...]VectorSearchtop-k=5LLM+ contextReplyRetrieval-Augmented Generation (RAG) Flow

RAG architecture: user prompts are embedded, matched against a vector store, then fed to an LLM with retrieved context.

Basic Atoms

// atoms/auth.ts
import { atom } from "jotai";
import { atomWithStorage } from "jotai/utils";

interface User {
  id
  name
  email
}

// Primitive atoms
export const userAtom = atomWithStorage<User | null>("user", null);
export const tokenAtom = atomWithStorage<string | null>("token", null);

// Derived atom (computed)
export const isAuthenticatedAtom = atom((get) => {
  return get(userAtom) !== null && get(tokenAtom) !== null;
});

// Async atom
export const userProfileAtom = atom(async (get) => {
  const token = get(tokenAtom);
  if (!token) return null;

  const response = await fetch("/api/profile", {
    headers: { Authorization: "Bearer " + token },
  });
  return response.json();
});

// Write-only atom (action)
export const loginAtom = atom(null, async (get, set, credentials: { email password }) => {
  const response = await fetch("/api/login", {
    method: "POST",
    body: JSON.stringify(credentials),
    headers: { "Content-Type": "application/json" },
  });
  const data = await response.json();
  set(userAtom, data.user);
  set(tokenAtom, data.token);
});

export const logoutAtom = atom(null, (get, set) => {
  set(userAtom, null);
  set(tokenAtom, null);
});

Using Atoms

import { useAtom, useAtomValue, useSetAtom } from "jotai";

function Header() {
  const isAuthenticated = useAtomValue(isAuthenticatedAtom);
  const user = useAtomValue(userAtom);
  const logout = useSetAtom(logoutAtom);

  if (!isAuthenticated) return <LoginButton />;

  return (
    <header>
      <span>Welcome, {user?.name}</span>
      <button  => logout()}>Logout</button>
    </header>
  );
}

Redux Toolkit: Enterprise Standard

Redux Toolkit (RTK) simplifies Redux with opinionated defaults, built-in Immer, and RTK Query for data fetching.

Setup

npm install @reduxjs/toolkit react-redux

Store Setup

// store/slices/authSlice.ts
import { createSlice, createAsyncThunk, PayloadAction } from "@reduxjs/toolkit";

interface AuthState {
  user: User | null;
  token | null;
  status: "idle" | "loading" | "failed";
  error | null;
}

const initialState: AuthState = {
  user: null,
  token: null,
  status: "idle",
  error: null,
};

export const login = createAsyncThunk(
  "auth/login",
  async (credentials: { email password }) => {
    const response = await fetch("/api/login", {
      method: "POST",
      body: JSON.stringify(credentials),
      headers: { "Content-Type": "application/json" },
    });
    return response.json();
  }
);

const authSlice = createSlice({
  name: "auth",
  initialState,
  reducers: {
    logout: (state) => {
      state.user = null;
      state.token = null;
    },
  },
  extraReducers: (builder) => {
    builder
      .addCase(login.pending, (state) => {
        state.status = "loading";
      })
      .addCase(login.fulfilled, (state, action) => {
        state.status = "idle";
        state.user = action.payload.user;
        state.token = action.payload.token;
      })
      .addCase(login.rejected, (state, action) => {
        state.status = "failed";
        state.error = action.error.message || "Login failed";
      });
  },
});

export const { logout } = authSlice.actions;
export default authSlice.reducer;

Store Configuration

Free Resource

Free Cloud Architecture Checklist

A 47-point checklist covering security, scalability, cost optimization, and disaster recovery for production cloud environments.

Download the Checklist
// store/index.ts
import { configureStore } from "@reduxjs/toolkit";
import authReducer from "./slices/authSlice";
import cartReducer from "./slices/cartSlice";

export const store = configureStore({
  reducer: {
    auth: authReducer,
    cart: cartReducer,
  },
});

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

Comparison

Feature Zustand Jotai Redux Toolkit
Bundle Size 1.1KB 2.4KB 11KB
Boilerplate Minimal Minimal Moderate
Provider Required No Optional Yes
DevTools Yes (via middleware) Yes (plugin) Yes (built-in)
Middleware Yes Limited Extensive
Server State No (use React Query) Async atoms RTK Query
Learning Curve Low Low Medium
Best For Most apps Fine-grained updates Large teams
RawDataPre-processTrainModelEvaluateMetricsDeployModelMonretrain loop

ML pipeline: from raw data collection through training, evaluation, deployment, and continuous monitoring.

When to Use What

  • Zustand: Best default choice. Simple API, no providers, works everywhere. Choose this unless you have a specific reason not to.
  • Jotai: Best when you need fine-grained reactivity (large forms, real-time data, complex derived state). Atoms prevent unnecessary re-renders naturally.
  • Redux Toolkit: Best for large teams with complex business logic, when you need time-travel debugging, and when RTK Query can replace your data-fetching layer.

At TechSaaS, we recommend Zustand for most new projects. Its simplicity-to-power ratio is unmatched. For complex dashboard applications with lots of derived state, Jotai's atomic model shines.

Need help with frontend architecture? Contact [email protected].

#react#state-management#zustand#jotai#redux#frontend

Related Service

Cloud Solutions

Let our experts help you build the right technology strategy for your business.

Need help with tutorials?

TechSaaS provides expert consulting and managed services for cloud infrastructure, DevOps, and AI/ML operations.

We Will Build You a Demo Site — For Free

Like it? Pay us. Do not like it? Walk away, zero complaints. You will spend way less than hiring developers or any agency.

47+ companies trusted us
99.99% uptime
< 48hr response

No spam. No contracts. Just a free demo.