Registry / web-framework / zundo
library2.3.0jsnpmunverified

Zundo is a lightweight (under 700 bytes) undo/redo middleware designed for Zustand, enabling robust time-travel capabilities in JavaScript and TypeScript applications. Currently at version 2.3.0, it is actively maintained and frequently updated to ensure compatibility with new Zustand versions, including both v4 and v5. Zundo differentiates itself through its minimal bundle size, high flexibility offered by various optional middleware configurations for performance optimization, and an unopinionated, extensible API. It integrates seamlessly with existing Zustand projects, working effectively with multiple stores within a single application to provide undo/redo functionality without significant overhead. Zundo facilitates managing complex state changes by providing simple yet powerful history management.

npm install zundo
INSTALL
IMPORT
SIG · ZUNDO
Z
zundo
web-frameworkjavascriptv2.3.0
Install
Import
Disk
Pass rate
0/ 6
Env Coverage0 / 6
glibc
1822
musl
1822
Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
node 18226 runs
build_error
glibc
node 18226 runs
build_error
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

temporal
import { temporal } from 'zundo';
import temporal from 'zundo'; // Not a default export
The `temporal` function is a named export, serving as the primary middleware for Zustand stores.
TemporalState
import type { TemporalState } from 'zundo';
Used for TypeScript to define the shape of the state managed by the temporal middleware, especially when accessing history details.
CommonJS require
const { temporal } = require('zundo');
const temporal = require('zundo'); // Requires destructuring
Since v2.0.2, zundo correctly supports both ESM and CommonJS. Ensure proper destructuring for CJS imports.

This example demonstrates how to create a Zustand store with `temporal` middleware, access its undo/redo capabilities, and reactively display historical state counts in a React component.

import { create } from 'zustand'; import { temporal } from 'zundo'; import { useStoreWithEqualityFn } from 'zustand/traditional'; import type { TemporalState } from 'zundo'; interface StoreState { bears: number; increasePopulation: () => void; removeAllBears: () => void; } const useStoreWithUndo = create<StoreState>()( temporal((set) => ({ bears: 0, increasePopulation: () => set((state) => ({ bears: state.bears + 1 })), removeAllBears: () => set({ bears: 0 }), })), ); // To access temporal functions and reactive temporal state interface MyTemporalState extends StoreState { temporal: TemporalState<StoreState>; } const useTemporalStore = () => useStoreWithEqualityFn(useStoreWithUndo.temporal.getState); const App = () => { const { bears, increasePopulation, removeAllBears } = useStoreWithUndo(); const { undo, redo, clear, pastStates, futureStates } = useTemporalStore(); return ( <> <h1>Bears: {bears}</h1> <button onClick={increasePopulation}>Increase</button> <button onClick={removeAllBears}>Remove All</button> <button onClick={() => undo()} disabled={pastStates.length === 0}>Undo</button> <button onClick={() => redo()} disabled={futureStates.length === 0}>Redo</button> <button onClick={() => clear()}>Clear History</button> <p>Past states count: {pastStates.length}</p> <p>Future states count: {futureStates.length}</p> </> ); }; export default App;
Debug
Known issues
breakingVersion 2.0.0 was a complete rewrite, introducing significant API changes and a new architecture. Users migrating from v1 will need to update their store definitions and temporal API calls.
fix
Refer to the v2 migration guide in the zundo GitHub repository for detailed steps on updating API usage.
affects: ^2.0.0
breakingVersion 2.0.1 temporarily changed the default module output from CommonJS (CJS) to ESM, which could break CJS-only environments. This was quickly rectified in v2.0.2.
fix
Ensure you are using zundo v2.0.2 or higher for proper CJS/ESM dual support, or configure your bundler to handle ESM if explicitly targeting it.
affects: 2.0.1
breakingIn v2.1.0, a bug fix for complex cases of `zundo` and an update to `handleSet` arguments (including `currentState` and `deltaState`) changed previously buggy behavior. If your application relied on the prior buggy behavior, this constitutes a breaking change.
fix
Review any custom `handleSet` logic after upgrading to v2.1.0 to ensure it aligns with the corrected behavior, particularly if you were indirectly relying on the bug.
affects: ^2.1.0
gotchaWhen accessing properties like `pastStates` or `futureStates` directly from `useStoreWithUndo.temporal.getState()`, these properties are not reactive in React components. Changes will not trigger re-renders.
fix
For reactive access to temporal properties, create a dedicated selector hook (e.g., `useTemporalStore` in the quickstart example) using `useStoreWithEqualityFn` from `zustand/traditional` or explicitly subscribe within your component.
affects: >=2.0.0
gotchaWith Zustand v5, the `setState` type became stricter. While zundo v2.3.0 supports these stricter types, applications upgrading to Zustand v5 might encounter TypeScript errors in their `set` calls if they previously used less strict types.
fix
Ensure your `set` calls within the Zustand store adhere to the stricter `setState` types introduced in Zustand v5. Consult the Zustand v5 migration guide for details on `setState` type changes.
affects: >=2.3.0 (when used with Zustand v5)
Errors
Common errors & fixes
TypeError: Cannot read properties of undefined (reading 'temporal')
Attempting to access `temporal` functions (e.g., `useStore.temporal.getState()`) before the middleware has been correctly applied or if the store itself is not initialized.
fix
Ensure `temporal` middleware is correctly wrapped around your `create` function: `create<StoreState>()(temporal((set) => ({...})))`. Also, verify that the store is imported and available where `temporal` is being accessed.
ModuleNotFoundError: Package path ./dist/esm/index.js is not exported from package ... (see exports field in .../node_modules/zundo/package.json)
This error specifically occurs if using zundo v2.0.1 in a CommonJS environment, as it temporarily broke CJS support by changing the default module output to ESM.
fix
Upgrade zundo to v2.0.2 or higher. Version 2.0.2 restored proper dual CJS/ESM support.
Argument of type '(set: StoreSet<StoreState>) => { ... }' is not assignable to parameter of type 'StoreInitializer<StoreState>'
TypeScript error related to `setState` arguments when using zundo with Zustand v5, often due to stricter `setState` types.
fix
Adjust your `set` calls within the store to conform to Zustand v5's stricter `setState` types, especially regarding the `replace` flag. Refer to Zustand's migration guide for v5 type changes.
Upgrade
Version history
2.3.0latest on npm
Audit
Dependencies
zustandrequiredCore state management library that zundo extends as middleware.
Agent activity
53 hits · last 30 days
node
44
OpenAI (training)
1
Resources
zundo — npm install zundo · libregistry