Back

Zustand Infinite Loops: How to spot and fix them

2026-02-20T10:30:00+07:005 min read

Zustand Infinite Loops: How to Spot and Fix Them

When building scalable applications with React and Zustand, infinite rendering loops are a common pitfall. They usually occur when selectors return new object references on every render.

Introduction

Zustand is fantastic because of its simplicity, but that simplicity means we have to be careful about referential equality in our selectors.

The Problem

If your selector looks like this:

const { users, activeUser } = useStore(state => ({
  users: state.users,
  activeUser: state.activeUser,
}))

You are returning a brand new object { users, activeUser } every time the store updates, even if users and activeUser haven't changed! React sees a new reference and re-renders the component.

The Solutions

1. Separate Selectors

The cleanest way is to use atomic selectors:

const users = useStore(state => state.users)
const activeUser = useStore(state => state.activeUser)

2. Shallow Equality

If you must return an object, use Zustand's useShallow hook imported from zustand/react/shallow.

import { useShallow } from 'zustand/react/shallow'

const { users, activeUser } = useStore(
  useShallow(state => ({
    users: state.users,
    activeUser: state.activeUser,
  })),
)

Conclusion

By understanding how React handles object references and how Zustand's subscription model works, you can easily avoid these performance-killing infinite loops.