npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

zustand-mutative

v2.0.0

Published

A Mutative middleware for Zustand enhances the efficiency of immutable state updates.

Readme

zustand-mutative

Node CI npm license

A Mutative middleware for Zustand enhances the efficiency of immutable state updates.

With the Mutative middleware, you can simplify the handling of immutable data in Zustand in a mutable way, allowing you to use immutable state more conveniently.

Performance

zustand-mutative runs the recipes that set() receives with Mutative 2, where zustand/middleware/immer runs them with Immer. In Mutative's benchmark of 97 workloads, Mutative 2.0 was about 3.6x as fast as Immer 11.1.18 with matched settings, and 6.6x as fast with each library's defaults, under which Immer freezes the next state and Mutative does not (geometric means). A hand-written reducer that copies only what it changes was faster still in most of those workloads. The performance summary has the complete results, the method and their limits.

Installation

In order to use the Mutative middleware in Zustand, you will need to install Mutative and Zustand as a direct dependency.

npm install zustand-mutative zustand mutative
# Or use any package manager of your choice.

| zustand-mutative | mutative | | ---------------- | -------- | | 2.x | 2.x | | 1.x | 1.x |

Upgrading to Mutative v2

zustand-mutative 2.x declares mutative ^2.0.0 as its peer dependency, so upgrade both together:

npm install zustand-mutative@2 mutative@2

The middleware API is unchanged: set() takes the same recipes, and mutative() takes the same options. The Mutative changes that can affect a store are:

  • With enableAutoFreeze: true, Map and Set instances in the state are frozen too, so adding a property to them or replacing one of their methods fails.
  • Mutative selects its development or production build from process.env.NODE_ENV. Define it in every bundle, including bundles for Node.js, and in production, match errors by their Minified Mutative error #<code> codes instead of their messages.
  • Mutative targets ES2018, and so does zustand-mutative; transpile both for older engines. Without a bundler, map mutative to its production ESM build, mutative/dist/mutative.esm.production.min.mjs, as its default ESM build reads process, or load its UMD build, which defines the Mutative global that the UMD build of zustand-mutative reads.

See the migration guide for every change in Mutative v2.

Usage

import { create } from 'zustand';
import { mutative } from 'zustand-mutative';

type State = {
  count: number;
};

type Actions = {
  increment: (qty: number) => void;
  decrement: (qty: number) => void;
};

export const useCountStore = create<State & Actions>()(
  mutative((set) => ({
    count: 0,
    increment: (qty: number) =>
      set((state) => {
        state.count += qty;
      }),
    decrement: (qty: number) =>
      set((state) => {
        state.count -= qty;
      }),
  }))
);

Mutative Options

With enableAutoFreeze: true, Mutative deeply freezes the next state that a recipe passed to set() produces. The initial state and objects passed to set() directly stay unfrozen until the next set() with a recipe, and the root state object stays unfrozen unless set() replaces the state, as in set(recipe, true): by default, Zustand merges the next state into a new root object.

Credits

zustand-mutative is inspired by zustand/middleware/immer.

License

zustand-mutative is MIT licensed.