persistNSync

raw JSON →
1.2.3 verified Sat Apr 25 auth: no javascript

Zustand middleware for persisting and syncing state across browser tabs, windows, and iframes (same origin). Current stable version is 1.2.3, released regularly with a focus on reliability. It uses the Broadcast Channel API for instant cross-tab synchronization and localStorage (or sessionStorage/cookies) for persistence. Differentiators include sub-1kB size, full TypeScript support, fire-and-forget state updates optimized for single-user systems, and exclude/include filters for selective syncing. Alternatives like zustand's built-in persist middleware lack cross-tab sync out of the box.

error Cannot find module 'persist-and-sync' or its corresponding type declarations.
cause Missing installation or TypeScript cannot locate types.
fix
Run 'npm install persist-and-sync' and ensure tsconfig.json includes 'node_modules' in 'typeRoots' or uses a bundler that resolves types.
error TypeError: persistNSync is not a function
cause Incorrect import: default import instead of named import.
fix
Change to 'import { persistNSync } from 'persist-and-sync';'
error Property 'persistNSync' does not exist on type 'typeof import("persist-and-sync")'.
cause CommonJS require without destructuring.
fix
Use 'const { persistNSync } = require('persist-and-sync');'
error Uncaught DOMException: Failed to construct 'BroadcastChannel': The origin 'null' is not allowed.
cause Running from file:// protocol (e.g., opening HTML directly). BroadcastChannel requires http:// or https:// origin.
fix
Serve the app via a local dev server (e.g., 'npx serve .' or use a framework dev server).
gotcha The middleware uses BroadcastChannel API which requires same-origin browsing contexts. It will not work across different origins.
fix Ensure all tabs/windows are on the same origin (protocol, host, port).
gotcha When using 'sessionStorage' for storage, the state is not persisted across sessions but still syncs across tabs within the same session.
fix Use 'localStorage' (default) if you need persistence across browser restarts.
deprecated The 'regExpToIgnore' option is deprecated since v1.2.0. Use 'exclude' with regex patterns instead.
fix Replace 'regExpToIgnore: /pattern/' with 'exclude: [/pattern/]' in the options object.
gotcha In a scenario with multiple writing tabs, only the last writing tab's state wins (fire-and-forget). This middleware is designed for single-user systems.
fix For collaborative editing or multi-writer conflicts, consider a different sync strategy or backend.
gotcha The middleware does not support partial syncing of nested state; include/exclude filters only apply to top-level keys.
fix Flatten nested state or create separate stores for subsets you want to filter.
npm install persist-and-sync
yarn add persist-and-sync
pnpm add persist-and-sync

Creates a Zustand store with persistNSync middleware; state is persisted to localStorage and synced across tabs.

import { create } from 'zustand';
import { persistNSync } from 'persist-and-sync';

type MyStore = {
  count: number;
  increment: () => void;
};

const useStore = create<MyStore>(
  persistNSync(
    (set) => ({
      count: 0,
      increment: () => set((state) => ({ count: state.count + 1 })),
    }),
    { name: 'counter-storage' }
  )
);

// In a React component:
function Counter() {
  const { count, increment } = useStore();
  return <button onClick={increment}>Count: {count}</button>;
}