Skip to main content
Version: 1.3.0

Optional Persistence

Component libraries do not always control whether an application has mounted a MnemonicProvider. The lean optional entrypoint lets those components keep one API: persist when a provider is available, or quietly use in-memory state when it is not.

When to use this

Reach for optional persistence when all of these are true:

  • the component may be used by apps that do not mount MnemonicProvider
  • you want one hook call instead of provider-detection logic at every call site
  • restoring the value is helpful when available, but not required for correctness

Use the regular useMnemonicKey(...) contract instead when a provider is a hard requirement and missing durable state should be treated as a setup mistake.

Pick the right entrypoint

EntrypointEstimated sizeUse when
react-mnemonic/optional~4.7 KBYou want the tiny component-library shim that falls back to local memory
react-mnemonic/core~58 KBA provider is required and you want the lean persisted-state path
react-mnemonic/schema~78 KBA provider is required and you want schema validation and migrations

These are rough current estimates based on the built ESM entry files in dist/ before consumer-side minification and tree-shaking. They are useful for relative comparison, not as a hard size guarantee.

Lean optional entrypoint

Use react-mnemonic/optional when you want the tiny fallback-first behavior:

import { useMnemonicKeyOptional } from "react-mnemonic/optional";

export function FilterChip() {
const { value, set, remove } = useMnemonicKeyOptional("selected", {
defaultValue: false,
});

return <button onClick={() => (value ? remove() : set(true))}>{value ? "Selected" : "Not selected"}</button>;
}
  • Inside MnemonicProvider: values persist normally through the provider-backed bridge.
  • Outside MnemonicProvider: the hook behaves like local component memory.

That means:

  • set(next) updates local state only when no provider exists
  • reset() restores defaultValue in memory
  • remove() forgets the current in-memory value so the hook shows the fallback/default again
  • onMount and onChange still run
  • codecs and schema metadata are inert without a provider

The lean entrypoint exports only:

  • useMnemonicKeyOptional(...)
  • useMnemonicOptional()
  • defineMnemonicKey(...)

App-side usage

The same component can opt into persistence automatically when an app wraps it with a provider:

import { MnemonicProvider } from "react-mnemonic/core";
import { SearchBox } from "@acme/search-ui";

export function App() {
return (
<MnemonicProvider namespace="search">
<SearchBox />
</MnemonicProvider>
);
}

Inside this boundary, useMnemonicKeyOptional("search-draft", ...) will persist to the provider namespace just like useMnemonicKey(...).

Schema-capable apps

Optional components can still participate in schema validation and migrations whenever the application mounts a schema-capable provider:

import { useMnemonicKeyOptional } from "react-mnemonic/optional";
import { MnemonicProvider } from "react-mnemonic/schema";

export function DensityPicker() {
const { value, set } = useMnemonicKeyOptional("settings", {
defaultValue: { density: "comfortable" as const },
schema: { version: 2 },
});

return (
<button
onClick={() =>
set({
density: value.density === "comfortable" ? "compact" : "comfortable",
})
}
>
Density: {value.density}
</button>
);
}

Without a provider, schema-specific persistence concerns are inert because no storage is being read or written.

Behavior matrix

HookWith providerWithout provider
useMnemonicKeyOptional(...)Normal persisted Mnemonic behavior through bridgeLocal in-memory state with the same return shape
useMnemonicOptional()Bridge metadata: namespace and capabilitiesnull

Low-level optional hooks

  • useMnemonicOptional() returns null without a provider.
  • Inside a provider, it returns lightweight bridge metadata: namespace plus capabilities.persistence and capabilities.schema.

Important caveats

  • The no-provider fallback is local memory, not durable storage.
  • The fallback state is not shared across unrelated component trees or browser tabs.
  • Lean optional hooks do not expose raw store helpers or recovery helpers.
  • Advanced persistence features such as reconciliation and cross-tab controls remain on the required-provider entrypoints.
  • If persistence is required for product correctness, do not use the optional hooks.