{"id":18026,"library":"zustand-sync-tabs","title":"Zustand Cross-Tab State Sync","description":"zustand-sync-tabs is a lightweight (~1KB minzipped) middleware for Zustand that facilitates seamless state synchronization across multiple browser tabs, windows, and iframes, provided they share the same origin. The current stable version is 0.2.3. It offers a 'fire and forget' setup, making it ideal for single-user applications that need consistent state across browsing contexts. Key differentiators include its small bundle size, full TypeScript support, and robust handling of one-writer/many-reader scenarios. It leverages the Broadcast Channel API (or localStorage fallback) for communication and supports both full and partial state sharing via include/exclude options for specific fields.","status":"active","version":"0.2.3","language":"javascript","source_language":"en","source_url":"https://github.com/react18-tools/zustand-sync-tabs","tags":["javascript","web","api","broadcast","channel","sync-tabs","sync-windows","sync","broadcast-channel","typescript"],"install":[{"cmd":"npm install zustand-sync-tabs","lang":"bash","label":"npm"},{"cmd":"yarn add zustand-sync-tabs","lang":"bash","label":"yarn"},{"cmd":"pnpm add zustand-sync-tabs","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core state management library that this package extends as a middleware.","package":"zustand","optional":false}],"imports":[{"note":"Primarily designed for ESM environments; CommonJS require is generally discouraged in modern Zustand setups, especially with TypeScript.","wrong":"const { syncTabs } = require('zustand-sync-tabs');","symbol":"syncTabs","correct":"import { syncTabs } from 'zustand-sync-tabs';"},{"note":"When using TypeScript, it's crucial to define your store's type for correct inference and strong typing within the middleware.","symbol":"MyStore","correct":"import { create } from 'zustand';\nimport { syncTabs } from 'zustand-sync-tabs';\n\ntype MyStore = {\n  count: number;\n  set: (n: number) => void;\n};"}],"quickstart":{"code":"import { create } from 'zustand';\nimport { syncTabs } from 'zustand-sync-tabs';\n\ntype MyStore = {\n  count: number;\n  text: string;\n  setCount: (n: number) => void;\n  setText: (s: string) => void;\n};\n\nconst useStore = create<MyStore>()(\n  syncTabs(\n    (set) => ({\n      count: 0,\n      text: 'Hello from main tab',\n      setCount: (n) => set({ count: n }),\n      setText: (s) => set({ text: s }),\n    }),\n    { \n      name: 'my-shared-channel', \n      exclude: ['text'] // Example: Exclude 'text' from syncing\n    }\n  )\n);\n\n// Example usage in a component or script:\n// const count = useStore((state) => state.count);\n// const setCount = useStore((state) => state.setCount);\n// console.log('Current count:', count);","lang":"typescript","description":"This quickstart demonstrates how to integrate `zustand-sync-tabs` middleware with a Zustand store. It shows a basic store definition, the application of `syncTabs` middleware with a channel name, and how to optionally exclude specific fields from synchronization. The store's `count` will sync across tabs, while `text` will remain local."},"warnings":[{"fix":"Replace `regExpToIgnore: /pattern/` with `exclude: [/pattern/]` or `exclude: ['fieldName']` in your `syncTabs` options.","message":"The `regExpToIgnore` option in SyncTabsOptionsType is deprecated and will be removed in future versions. Users should migrate to the `exclude` option, which accepts an array of strings or RegExp patterns for more flexible filtering.","severity":"deprecated","affected_versions":">=0.2.0"},{"fix":"Ensure all browsing contexts requiring synchronization are hosted on the exact same origin (protocol, host, and port).","message":"State synchronization is limited to tabs/windows/iframes that share the 'same origin'. Cross-origin communication is not supported due to browser security restrictions (e.g., between `example.com` and `sub.example.com` unless specifically configured via `document.domain`).","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"For persistence and cross-tab sync, consider using `persist-and-sync` or carefully test the order of middleware application. A common pattern is `create(persist(syncTabs(...)))` or `create(syncTabs(persist(...)))` depending on desired interaction, but using a dedicated solution might be simpler.","message":"If using this middleware in combination with `zustand/persist`, ensure `syncTabs` is applied *inside* `persist` or configured carefully. The README recommends `persist-and-sync` if local persistence and cross-tab sync are both required, suggesting potential interaction complexities if managed independently.","severity":"gotcha","affected_versions":">=0.1.0"}],"env_vars":null,"last_verified":"2026-04-23T00:00:00.000Z","next_check":"2026-07-22T00:00:00.000Z","problems":[{"fix":"Ensure `syncTabs` wraps your store's `(set) => ({ ... })` definition correctly, e.g., `create(syncTabs(set => ({ ... }), { name: '...' }))`.","cause":"The `syncTabs` middleware expects a valid Zustand store creator function as its first argument.","error":"TypeError: Cannot read properties of undefined (reading 'getState')"},{"fix":"Verify that the `name` property in the `syncTabs` options is an exact match (case-sensitive) for all instances of your store across different tabs. Also, confirm that all tabs are on the 'same origin'.","cause":"This usually indicates that the 'name' option provided to `syncTabs` middleware is not identical across all browsing contexts, or the contexts are not on the same origin.","error":"State not syncing between tabs/windows."}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}