Skip to content
brix.v2 stable

Search documentation

70 guides

Documentation menu
Docs / Pages and UI / Browser storageRead Markdown ↗

Bind browser storage to components

Define schema-validated storage keys and bind local or session storage reactively to Preact and React components.

Storage is persisted client state. For in-memory coordination across Preact island roots on one page, use stores instead.

Define keys once

Use the framework-owned Zod export and colocate reusable keys with the feature that owns them:

import { createStorageKey } from "brix/storage";
import { z } from "brix/zod";

export const themeKey = createStorageKey("theme", z.enum(["light", "dark"]));
export const profileKey = createStorageKey(
  "profile",
  z.object({ displayName: z.string(), visits: z.number().int().nonnegative() }),
);

A StorageKey is the plain { key, schema } definition. Reuse it rather than repeating a string and schema or spreading the definition. Reads, writes, and hooks also accept an inline (key, schema) pair, but a schema is never optional. Removal accepts either a storage key or a string because no value needs validation.

Choose stable, application-specific key names. Schema changes must tolerate data written by an older application version or deliberately treat it as missing.

Use reactive hooks

"use island";

import { useLocalStorage } from "brix/hooks";
import { themeKey } from "./storage-keys.ts";

export function ThemePicker() {
  const theme = useLocalStorage(themeKey);

  return (
    <select
      value={theme.value ?? "light"}
      onChange={(event) => {
        const value = event.currentTarget.value;
        if (value === "light" || value === "dark") theme.set(value);
      }}
    >
      <option value="light">Light</option>
      <option value="dark">Dark</option>
    </select>
  );
}

useLocalStorage and useSessionStorage return:

  • value, the parsed schema output or null when absent, invalid, or unavailable.
  • set(value), a typed write that validates and updates reactive state after persistence succeeds.
  • remove(), which removes the item and updates subscribers.

Hooks for the same storage object and key synchronize within the current document, including changes made through Brix raw helpers. Local-storage hooks also consume browser storage events, so another tab's write re-renders subscribers. Session storage is tab-scoped and does not synchronize across tabs.

For an app-specific Storage implementation, use useStorage(customStorage, storageKey) from the matching Preact or React binding.

Continue with use typed browser storage helpers.