createStorageValuesStore
Creates a reactive nanostore that mirrors the entire contents of a storage backend.
Signature
function createStorageValuesStore( adapter: StorageAdapter, options?: StorageValuesStoreOptions,): StorageValuesStore;Parameters
adapter
The storage adapter to use.
| Type | Description |
|---|---|
StorageAdapter | Single adapter (arrays not supported) |
options
Optional configuration object.
interface StorageValuesStoreOptions { listen?: boolean;}| Option | Type | Default | Description |
|---|---|---|---|
listen | boolean | false | Enable cross-tab sync |
Return Value
Returns a StorageValuesStore object:
interface StorageValuesStore { readonly $value: ReadableAtom<Record<string, string>>; get: { (): Record<string, string>; (key: string): string | null; }; set: (key: string, value: string) => void; update: (values: Record<string, string>) => void; update: (fn: (current: Record<string, string>) => Record<string, string>) => void; remove: (key: string) => void; remove: (keys: string[]) => void; clear: () => void; sync: () => void; readonly listener: StorageListener;}$value
A nanostores ReadableAtom containing all key-value pairs. Use methods to modify.
// Subscribe to changesstore.$value.subscribe((values) => { console.log("Storage contents:", values);});get() / get(key)
Returns all values or a single value by key.
// Get all valuesconst values = store.get();// { "key1": "value1", "key2": "value2" }
// Get single valueconst value = store.get("key1"); // "value1" or nullset(key, value)
Sets a single key-value pair.
store.set("username", "Alice");update(values) / update(fn)
Updates multiple values or uses a function to compute new values.
If the function returns the same reference (current), no update is triggered.
// Merge new valuesstore.update({ key1: "value1", key2: "value2" });
// Functional update with conditional logicstore.update((current) => { const count = current["count"]; // Only increment if count exists and is a valid number if (count !== undefined && !isNaN(parseInt(count, 10))) { return { ...current, count: String(parseInt(count, 10) + 1) }; } // Return current to skip update (no changes) return current;});
// Replace entirelystore.update(() => ({ onlyThisKey: "value" }));remove(key) / remove(keys)
Removes one or more keys from storage.
// Remove single keystore.remove("username");
// Remove multiple keysstore.remove(["key1", "key2", "key3"]);clear()
Clears all values from storage.
store.clear();// Storage is now emptyconsole.log(store.get()); // {}sync()
Force sync from storage to store. Useful when:
listen: falseand you want to manually refresh- Polling for same-tab changes from other libraries (with
setInterval) - Using adapters without event support (e.g., cookies)
// Manual refresh when listen: falsestore.sync();listener
Controls cross-tab synchronization. Same interface as createStorageStore.
interface StorageListener { on: () => void; off: () => void; toggle: () => void; readonly $on: ReadableAtom<boolean>;}Examples
Basic Usage
import { createStorageValuesStore, localStorageAdapter } from "@vp-tw/nanostores-storage";
const storage = createStorageValuesStore(localStorageAdapter);
// Read allconsole.log(storage.get()); // { ... }
// Read single valueconsole.log(storage.get("theme")); // "dark" or null
// Set single valuestorage.set("theme", "dark");
// Update multiplestorage.update({ language: "en", timezone: "UTC" });
// Removestorage.remove("theme");
// Clear allstorage.clear();With Cross-Tab Sync
const storage = createStorageValuesStore(localStorageAdapter, { listen: true,});
// Updates when another tab modifies localStoragestorage.$value.subscribe((values) => { console.log("Storage updated:", Object.keys(values).length, "keys");});Conditional Update (No-op Pattern)
const storage = createStorageValuesStore(localStorageAdapter);
// Only increment if "counter" exists and is a numberstorage.update((current) => { const count = current["counter"]; if (count !== undefined && !isNaN(parseInt(count, 10))) { return { ...current, counter: String(parseInt(count, 10) + 1) }; } // Return current reference to skip update return current;});React Integration
import { useStore } from "@nanostores/react";import { createStorageValuesStore, localStorageAdapter } from "@vp-tw/nanostores-storage";
const storage = createStorageValuesStore(localStorageAdapter, { listen: true,});
function StorageViewer() { const values = useStore(storage.$value);
return ( <ul> {Object.entries(values).map(([key, value]) => ( <li key={key}> <strong>{key}:</strong> {value} <button onClick={() => storage.remove(key)}>Remove</button> </li> ))} </ul> );}sessionStorage Monitoring
import { createStorageValuesStore, sessionStorageAdapter } from "@vp-tw/nanostores-storage";
const sessionStorage = createStorageValuesStore(sessionStorageAdapter);
// Monitor all session datasessionStorage.$value.subscribe((values) => { console.log("Session data:", values);});Use Cases
- DevTools: Build a storage inspector/editor
- Debug Panel: Monitor storage changes in development
- Sync UI: Display all stored preferences
- Migration: Copy/transform storage contents
- Backup: Export storage to JSON
See Also
- createStorageStore — Single-key storage
- StorageAdapter — Adapter interface
- Cross-Tab Sync — How listening works