useDimStore: Dim Storage from React
Mixed applications can host Dim web components alongside React trees. The useDimStore hook lets React components read and write the same encrypted IndexedDB keys that Dim’s useStore uses — without mounting a custom element.
When to use it
| Hook | Runtime | Use case |
|---|---|---|
useStore | Dim web component | Bottom-up state inside <my-app> |
useDimStore | React | Shell, settings page, or legacy React UI sharing Dim persistence |
Both write to DimDatabase / DimStore with compatible encryption when using the same password and key paths.
API
import { useDimStore } from "@dim/core"; // or relative path to dim.ts
const [value, setValue, isLoading] = useDimStore({
key: "user.displayName", // IndexedDB key (same as useStore path)
password: "my-encryption-key", // required — no default
defaultValue: "", // optional initial when key missing
});
Parameters
| Option | Required | Description |
|---|---|---|
key | Yes | Flat string key matching useStore leaf paths (e.g. "cart", "form.input") |
password | Yes | Encryption key; must match useStore(..., { encryptionKey }) |
defaultValue | No | Used when no record exists or decryption fails |
Return tuple
Same shape as Dim loading-aware state, minus setIsLoading:
- value — current string (extend pattern for JSON strings if needed)
- setValue — async setter; encrypts, writes IndexedDB, dispatches cross-tab event
- isLoading —
trueuntil initial read completes
React example
import React from "react";
import { useDimStore } from "../dim/src/core/dim.ts";
function DisplayNameSettings() {
const [name, setName, isLoading] = useDimStore({
key: "user.name",
password: process.env.REACT_APP_STORE_KEY,
defaultValue: "Guest",
});
if (isLoading) {
return <p>Loading…</p>;
}
return (
<label>
Display name
<input
value={name}
onChange={(e) => setName(e.target.value)}
/>
</label>
);
}
Dim web components using:
useStore({ user: { name: useState("") } }, { encryptionKey: process.env.REACT_APP_STORE_KEY });
…will receive updates when the React field changes, and vice versa, via the shared event + IndexedDB layer.
Encryption requirements
useDimStore always encrypts. An explicit password is mandatory:
// Throws at hook init
useDimStore({ key: "x", password: "" });
There is no plaintext mode in useDimStore. For unencrypted shared keys, use useStore in a thin Dim wrapper component instead.
Wrong passwords log warnings and fall back to defaultValue rather than exposing ciphertext structures to the UI.
Event sync internals
On setValue:
- Local React state updates immediately
- Value encrypts via
CryptoManager StorageManager.writeValuepersists to IndexedDB- Debounced
CustomEventonwindow(key = store key) notifies other tabs/components
Listeners skip events originating from the same hook instance (_instanceId) to prevent loops.
Module Federation setup
In federated apps, expose Dim from the remote:
// webpack ModuleFederationPlugin
exposes: {
"./dim": "./src/core/dim.ts",
}
React host:
const { useDimStore } = await import("dimRemote/dim");
Ensure a single copy of crypto/storage manager state per password (handled internally via module-level maps).
Limitations
- String-oriented API — return type is
string; serialize objects withJSON.stringify/parseat the boundary - Encrypted only — no plaintext React bridge hook today
- Key path strings — must match
useStoredot-path conventions exactly
See dim/todo.md for future interop improvements.
Conclusion
useDimStore bridges React and Dim persistence so you can migrate screen-by-screen to web components without splitting user data.