Home » 🐻 How to Use Zustand in a Next.js App with TypeScript
Posted in

🐻 How to Use Zustand in a Next.js App with TypeScript

Managing global state in a React app can get messy fast. Context API is sometimes too basic, Redux can be overkill, and Recoil or Jotai might feel unfamiliar. If you’re looking for a minimal, scalable, and TypeScript-friendly state management tool for your Next.js app, Zustand is a dream come true.

In this post, I’ll walk you through how to set up and use Zustand in a Next.js project with TypeScriptβ€”step by step.


πŸ€” What is Zustand?

Zustand (German for “state”) is a tiny, fast, and scalable state management library for React. Created by the developers of Jotai and React Spring, it offers a simple API with zero boilerplate and excellent TypeScript support.

Why choose Zustand?

  • βœ… Minimal setup
  • ⚑ Super fast
  • πŸ” Works with server and client
  • πŸ’– TypeScript support out of the box
  • πŸ”§ Built-in middleware like persist and devtools

βš™οΈ Step 1: Set Up Your Next.js + TypeScript App

If you haven’t already created a Next.js app:

npx create-next-app@latest zustand-demo --typescript
cd zustand-demo

Then install Zustand:

npm install zustand

🐻 Step 2: Create a Zustand Store

Let’s create a simple counter store.

Create a new file: stores/counterStore.ts

import { create } from 'zustand';

interface CounterState {
  count: number;
  increase: () => void;
  decrease: () => void;
  reset: () => void;
}

export const useCounterStore = create<CounterState>((set) => ({
  count: 0,
  increase: () => set((state) => ({ count: state.count + 1 })),
  decrease: () => set((state) => ({ count: state.count - 1 })),
  reset: () => set({ count: 0 }),
}));

Here:

  • We define a CounterState interface for strong typing.
  • The store has three actions and one state variable (count).

πŸ’» Step 3: Use the Store in a Component

In pages/index.tsx, use the state:

import { useCounterStore } from '@/stores/counterStore';

export default function Home() {
  const { count, increase, decrease, reset } = useCounterStore();

  return (
    <main className="min-h-screen flex flex-col items-center justify-center text-center p-4">
      <h1 className="text-4xl font-bold mb-4">Zustand + Next.js πŸ’₯</h1>
      <p className="text-2xl mb-4">Count: {count}</p>
      <div className="space-x-2">
        <button onClick={increase} className="px-4 py-2 bg-green-500 text-white rounded">+</button>
        <button onClick={decrease} className="px-4 py-2 bg-red-500 text-white rounded">-</button>
        <button onClick={reset} className="px-4 py-2 bg-gray-500 text-white rounded">Reset</button>
      </div>
    </main>
  );
}

Boom πŸ’₯ β€” live global state with zero prop drilling or context nesting.


πŸ”„ Bonus: Zustand Persist Middleware

Want to persist state across reloads? Use the persist middleware.

npm install zustand/middleware

Then update the store like this:

import { create } from 'zustand';
import { persist } from 'zustand/middleware';

interface CounterState {
  count: number;
  increase: () => void;
  decrease: () => void;
  reset: () => void;
}

export const useCounterStore = create<CounterState>()(
  persist(
    (set) => ({
      count: 0,
      increase: () => set((state) => ({ count: state.count + 1 })),
      decrease: () => set((state) => ({ count: state.count - 1 })),
      reset: () => set({ count: 0 }),
    }),
    {
      name: 'counter-storage', // localStorage key
    }
  )
);

Now your counter value will persist between refreshes!


🧠 Bonus: Zustand + Next.js SSR

Zustand is client-side by default, but you can hydrate it for SSR if needed. However, for most use cases (UI state, filters, settings, etc.), client-only is perfectly fine.


βœ… Final Thoughts

Zustand is a lightweight, powerful solution that plays beautifully with Next.js and TypeScript. It gives you just enough to manage state without all the Redux ceremony or Context API verbosity.

Perfect for:

  • UI state
  • Global modals
  • Dark mode toggles
  • Auth/session state
  • Cart logic (e-commerce)

πŸ§ͺ Want More?

Let me know if you want:

  • Zustand with middleware logging
  • Zustand with auth/session handling
  • Zustand + server actions or Supabase sync
  • Zustand across multiple stores

Happy coding! 🧠✨
Let the bear manage your state so you can focus on building cool stuff.

Leave a Reply

Your email address will not be published. Required fields are marked *