{"id":18659,"library":"persist-and-sync","title":"persistNSync","description":"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.","status":"active","version":"1.2.3","language":"javascript","source_language":"en","source_url":"https://github.com/react18-tools/persist-and-sync","tags":["javascript","web","api","broadcast","channel","sync-tabs","sync-windows","sync","broadcast-channel","typescript"],"install":[{"cmd":"npm install persist-and-sync","lang":"bash","label":"npm"},{"cmd":"yarn add persist-and-sync","lang":"bash","label":"yarn"},{"cmd":"pnpm add persist-and-sync","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency - middleware designed for zustand stores","package":"zustand","optional":false}],"imports":[{"note":"This is a named export, not a default export.","wrong":"import persistNSync from 'persist-and-sync'","symbol":"persistNSync","correct":"import { persistNSync } from 'persist-and-sync'"},{"note":"This type is only available as a type export for TypeScript. Use 'import type' to avoid emitting runtime code.","wrong":"import { PersistNSyncOptions } from 'persist-and-sync'","symbol":"PersistNSyncOptions","correct":"import type { PersistNSyncOptions } from 'persist-and-sync'"},{"note":"CommonJS require must destructure the named export.","wrong":"const persistNSync = require('persist-and-sync')","symbol":"persistNSync (CommonJS)","correct":"const { persistNSync } = require('persist-and-sync')"}],"quickstart":{"code":"import { create } from 'zustand';\nimport { persistNSync } from 'persist-and-sync';\n\ntype MyStore = {\n  count: number;\n  increment: () => void;\n};\n\nconst useStore = create<MyStore>(\n  persistNSync(\n    (set) => ({\n      count: 0,\n      increment: () => set((state) => ({ count: state.count + 1 })),\n    }),\n    { name: 'counter-storage' }\n  )\n);\n\n// In a React component:\nfunction Counter() {\n  const { count, increment } = useStore();\n  return <button onClick={increment}>Count: {count}</button>;\n}","lang":"typescript","description":"Creates a Zustand store with persistNSync middleware; state is persisted to localStorage and synced across tabs."},"warnings":[{"fix":"Ensure all tabs/windows are on the same origin (protocol, host, port).","message":"The middleware uses BroadcastChannel API which requires same-origin browsing contexts. It will not work across different origins.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Use 'localStorage' (default) if you need persistence across browser restarts.","message":"When using 'sessionStorage' for storage, the state is not persisted across sessions but still syncs across tabs within the same session.","severity":"gotcha","affected_versions":">=1.1.0"},{"fix":"Replace 'regExpToIgnore: /pattern/' with 'exclude: [/pattern/]' in the options object.","message":"The 'regExpToIgnore' option is deprecated since v1.2.0. Use 'exclude' with regex patterns instead.","severity":"deprecated","affected_versions":">=1.2.0"},{"fix":"For collaborative editing or multi-writer conflicts, consider a different sync strategy or backend.","message":"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.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Flatten nested state or create separate stores for subsets you want to filter.","message":"The middleware does not support partial syncing of nested state; include/exclude filters only apply to top-level keys.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-25T00:00:00.000Z","next_check":"2026-07-24T00:00:00.000Z","problems":[{"fix":"Run 'npm install persist-and-sync' and ensure tsconfig.json includes 'node_modules' in 'typeRoots' or uses a bundler that resolves types.","cause":"Missing installation or TypeScript cannot locate types.","error":"Cannot find module 'persist-and-sync' or its corresponding type declarations."},{"fix":"Change to 'import { persistNSync } from 'persist-and-sync';'","cause":"Incorrect import: default import instead of named import.","error":"TypeError: persistNSync is not a function"},{"fix":"Use 'const { persistNSync } = require('persist-and-sync');'","cause":"CommonJS require without destructuring.","error":"Property 'persistNSync' does not exist on type 'typeof import(\"persist-and-sync\")'."},{"fix":"Serve the app via a local dev server (e.g., 'npx serve .' or use a framework dev server).","cause":"Running from file:// protocol (e.g., opening HTML directly). BroadcastChannel requires http:// or https:// origin.","error":"Uncaught DOMException: Failed to construct 'BroadcastChannel': The origin 'null' is not allowed."}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}