{"id":18024,"library":"zustand-mutative","title":"Mutative Middleware for Zustand","description":"zustand-mutative is a middleware for Zustand that integrates the Mutative library, enabling efficient and convenient immutable state updates using a mutable syntax. It allows developers to modify Zustand state directly, similar to libraries like Immer, but claims significantly higher performance (2-6x faster than spread operations, over 10x faster than `zustand/middleware/immer`). The current stable version is 1.3.1. Releases appear to be driven by dependency updates and minor fixes, with new versions roughly every few months, often coinciding with updates to `mutative` or `zustand` itself. Its key differentiator is its performance advantage over other immutable update helpers within the Zustand ecosystem while providing a familiar mutable-style API for state management.","status":"active","version":"1.3.1","language":"javascript","source_language":"en","source_url":"https://github.com/mutativejs/zustand-mutative","tags":["javascript","zustand","mutative","middleware","immutable","typescript"],"install":[{"cmd":"npm install zustand-mutative","lang":"bash","label":"npm"},{"cmd":"yarn add zustand-mutative","lang":"bash","label":"yarn"},{"cmd":"pnpm add zustand-mutative","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core dependency for mutable-style immutable state updates.","package":"mutative","optional":false},{"reason":"The state management library this middleware extends.","package":"zustand","optional":false},{"reason":"Peer dependency for Zustand stores used in React environments.","package":"react","optional":true},{"reason":"TypeScript type definitions for React, required for type checking in React environments.","package":"@types/react","optional":true}],"imports":[{"note":"Primarily designed for ESM and TypeScript usage. While CommonJS `require` might work with transpilation, direct ESM import is idiomatic and recommended.","wrong":"const mutative = require('zustand-mutative').mutative;","symbol":"mutative","correct":"import { mutative } from 'zustand-mutative';"},{"note":"`create` is a named export from `zustand`, not a default export.","wrong":"import create from 'zustand';","symbol":"create","correct":"import { create } from 'zustand';"},{"note":"Using TypeScript generics `<State & Actions>` is crucial for type safety when defining your store with `zustand-mutative`.","wrong":"create(mutative((set) => ({ ... })));","symbol":"StoreDefinition","correct":"create<State & Actions>()(mutative((set) => ({ ... })));"}],"quickstart":{"code":"import { create } from 'zustand';\nimport { mutative } from 'zustand-mutative';\n\ntype State = {\n  count: number;\n  items: { id: string; value: number }[];\n};\n\ntype Actions = {\n  increment: (qty: number) => void;\n  decrement: (qty: number) => void;\n  addItem: (id: string, value: number) => void;\n  updateItem: (id: string, newValue: number) => void;\n};\n\nexport const useCountStore = create<State & Actions>()(\n  mutative((set) => ({\n    count: 0,\n    items: [],\n    increment: (qty: number) =>\n      set((state) => {\n        state.count += qty;\n      }),\n    decrement: (qty: number) =>\n      set((state) => {\n        state.count -= qty;\n      }),\n    addItem: (id: string, value: number) =>\n      set((state) => {\n        state.items.push({ id, value });\n      }),\n    updateItem: (id: string, newValue: number) =>\n      set((state) => {\n        const item = state.items.find((item) => item.id === id);\n        if (item) {\n          item.value = newValue;\n        }\n      }),\n  }))\n);\n\n// Example usage (not part of the store definition, but runnable)\n// const store = useCountStore.getState();\n// store.increment(5);\n// store.addItem('a', 10);\n// store.updateItem('a', 20);\n// console.log(useCountStore.getState().count); // Expected: 5\n// console.log(useCountStore.getState().items); // Expected: [{ id: 'a', value: 20 }]","lang":"typescript","description":"This quickstart demonstrates how to define a Zustand store using `zustand-mutative` middleware, enabling direct, mutable-style updates to an immutable state object, including primitive values and array/object mutations."},"warnings":[{"fix":"Ensure your project's `zustand` and `mutative` versions meet the peer dependency requirements specified in `zustand-mutative`'s `package.json` (e.g., `zustand: ^4.0 || ^5.0`, `mutative: ^1.3.0`).","message":"Version 1.1.0 upgraded its peer dependencies, specifically `zustand` to `v5` and `mutative` to `v1.1.0`. Users on older major versions of these dependencies will need to upgrade them to match, which may introduce breaking changes from those libraries themselves.","severity":"breaking","affected_versions":">=1.1.0"},{"fix":"Within the `set` callback provided to `mutative`, ensure all state changes are done by directly mutating the `state` parameter, e.g., `state.count += 1;`.","message":"When performing updates within the `set` function, always modify the `state` object directly. Returning a new object from `set` when using `mutative` middleware will bypass its capabilities and potentially lead to unexpected behavior or performance degradation.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Evaluate the complexity of your state updates. For simple, shallow changes, direct `set` with spread syntax is an option. For nested, complex, or performance-critical immutable updates, `zustand-mutative` is recommended.","message":"The `mutative` middleware is designed for scenarios where you need to perform complex nested updates efficiently. For very simple, shallow updates, directly using Zustand's `set` with spread syntax (`set((state) => ({ ...state, key: newValue }))`) might be sufficient and avoid the overhead of a middleware.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"If encountering peer dependency issues with React, ensure your React version is within the supported range (`^17.0 || ^18.0 || ^19.0`). Consider using `legacy-peer-deps` or similar options with your package manager temporarily if you are unable to upgrade React immediately.","message":"Version 1.2.0 added support for React v19 as a peer dependency. While this is generally an improvement, projects specifically locking to older React versions should be aware of potential dependency resolution conflicts if their package manager strictly enforces peer dependencies.","severity":"breaking","affected_versions":">=1.2.0"}],"env_vars":null,"last_verified":"2026-04-23T00:00:00.000Z","next_check":"2026-07-22T00:00:00.000Z","problems":[{"fix":"Ensure you are importing the `mutative` middleware from `zustand-mutative` like so: `import { mutative } from 'zustand-mutative';`.","cause":"Attempting to import `mutative` from the `mutative` package instead of `zustand-mutative`.","error":"Error: 'mutative' does not contain an export named 'mutative'."},{"fix":"Ensure the `mutative` middleware is correctly wrapped around your store definition. If you've enabled `autoFreeze` in Mutative options, all mutations must occur within the `set` callback provided by `zustand-mutative`. Check Mutative's strict mode documentation for more advanced debugging.","cause":"This error can occur if `zustand-mutative` is not correctly applied or if `mutative`'s auto-freeze option is enabled in development, and you are trying to mutate a frozen object outside the `set` callback, or if strict mode issues are present.","error":"TypeError: Cannot assign to read only property 'foo' of object '#<Object>'"},{"fix":"Ensure `zustand-mutative` is correctly installed. For `NodeNext` resolution issues, verify your `tsconfig.json` and `package.json` (`exports` field) are configured correctly, or update to `zustand-mutative@^1.2.1` or later which includes fixes for these types of import issues.","cause":"TypeScript cannot find the module or its types. This often happens due to incorrect module resolution settings (e.g., `moduleResolution: 'NodeNext'` without proper `package.json` exports mapping) or outdated package installations.","error":"TS2307: Cannot find module 'zustand-mutative' or its corresponding type declarations."}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}