Eljan Simuratli
3/10/2026
ADVANCED ZUSTAND "1". Zustand Mental Model: How it Differs from Redux?

ADVANCED ZUSTAND “1”. Zustand Mental Model: How it Differs from Redux?
What is Global State?
- The data needed by multiple components
- Situations where we don’t want to perform prop drilling.
- Values that must stay synchronized across different parts of the UI
Example: Auth User
function Navbar() { const user = ??? // needs access}function Dashboard() { const user = ??? // also needs access}
If you lift the state too high, you get prop drilling:
<App user={user}> <Layout user={user}> <Navbar user={user} /> <Dashboard user={user} /> </Layout></App>
Redux solves this problem using the Flux architecture.
But the real question is:
Does global state really need reducer + action + dispatch every time?
The Redux Mental Model:
Action -> Reducer -> Store -> Re-render
Example:
dispatch({ type: "SET_USER", payload: user }) //Action
// Reducerfunction reducer(state = initialState, action) { switch (action.type) { case "SET_USER": return { ...state, user: action.payload } default: return state }}
//Componentconst user = useSelector((state) => state.user)
Redux is predictable because it treats state changes like domain events.
This is powerful for:
- Complex business workflows
- Audit trails
- Large enterprise systems
- Time-travel debugging
But here’s the cost:
- Boilerplate
- Indirection
- Mental overhead
Even a simple UI state becomes ceremonial.
The Breaking Point: UI State vs Business State
Consider this example: You want to open a modal.
Redux version:
//Actiondispatch({ type: "OPEN_MODAL" })//Reducercase "OPEN_MODAL": return { ...state, isModalOpen: true }
Now compare Zustand.
Zustand Mental Model (Subscription-Based State).
Zustand removes the event pipeline.
import { create } from "zustand"const useStore = create((set) => ({ user: null, isModalOpen: false, setUser: (user) => set({ user }), openModal: () => set({ isModalOpen: true }), closeModal: () => set({ isModalOpen: false }),}))
Component:
const isModalOpen = useStore((s) => s.isModalOpen)const openModal = useStore((s) => s.openModal)
Mental model:
- Components subscribe to specific slices
- Calling set() updates state
- Only affected subscribers re-render
The Critical Difference: Subscription Granularity
Redux subscription:
const user = useSelector((state) => state.user)
Zustand subscription:
const user = useStore((s) => s.user)
Superficially similar.
But here’s the important part:
In Zustand, each selector creates an independent subscription.
Example:
const user = useStore((s) => s.user)const theme = useStore((s) => s.theme)
If theme changes:
→ user component does NOT re-render.
If you do this instead:
const state = useStore()
Now you subscribe to everything. That’s where performance problems begin. Understanding this is the first advanced step.
Performance Example: Why Mental Model Matters
Let’s simulate a heavy component:
function ExpensiveComponent() { const user = useStore((s) => s.user) console.log("rendering expensive component") return <div>{user?.name}</div>}
Now imagine another part of the app updates:
set({ theme: "dark" })
If your selector is correct:
→ ExpensiveComponent does NOT re-render.
If you destructured the entire state:
const { user, theme } = useStore()
→ It will re-render unnecessarily.
This is why understanding the subscription model matters.
Architectural Philosophy Shift
Redux philosophy:
State change = domain event
A domain event represents a real-world event that occurred within the application’s business logic. "ORDER_CREATED" , "PAYMENT_COMPLATED"
Zustand philosophy:
State change = mutation through controlled setter
Redux enforces discipline through structure.
Zustand gives you flexibility — and expects you to be disciplined.
This is a big mental shift.
Redux is strict by design. Zustand is minimal by design.
Flux Pattern?
Redux is a direct Flux implementation. But Zustand not
Zustand:
- Does not impose Unidirectional flow
- Reducer is not necessary
- It leaves mutation control up to you.
But:
Not applying Zustand Flux doesn’t mean it’s chaotic.
Actually:
Zustand is a subscription-based state container.
This is a crucial difference in mental models.
When Redux Is Actually Better
Let’s be honest.
Redux is better when:
- You need strict event logs
- You require deterministic replay
- You have highly complex async flows
- You rely on domain-driven architecture
Example:
Order lifecycle in e-commerce:
ORDER_CREATEDORDER_PAIDORDER_SHIPPEDORDER_REFUNDED
When Zustand Feels Right
- UI-heavy dashboards
- SaaS admin panels
- Chrome extensions
- Feature flags
- Modal management
- Filters & sorting
Most frontend apps are 70% UI state, 30% domain state.
Using Redux for everything can be overkill.
ADVANCED ZUSTAND "2". Selectors, Equality Functions, and Re-render Controls
ADVANCED ZUSTAND "2". Selectors, Equality Functions, and Re-render Controls Part 2 is about performance mastery…simuratli.medium.com