Skip to main content

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

HookRuntimeUse case
useStoreDim web componentBottom-up state inside <my-app>
useDimStoreReactShell, 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

OptionRequiredDescription
keyYesFlat string key matching useStore leaf paths (e.g. "cart", "form.input")
passwordYesEncryption key; must match useStore(..., { encryptionKey })
defaultValueNoUsed when no record exists or decryption fails

Return tuple

Same shape as Dim loading-aware state, minus setIsLoading:

  1. value — current string (extend pattern for JSON strings if needed)
  2. setValue — async setter; encrypts, writes IndexedDB, dispatches cross-tab event
  3. isLoadingtrue until 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:

  1. Local React state updates immediately
  2. Value encrypts via CryptoManager
  3. StorageManager.writeValue persists to IndexedDB
  4. Debounced CustomEvent on window (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 with JSON.stringify / parse at the boundary
  • Encrypted only — no plaintext React bridge hook today
  • Key path strings — must match useStore dot-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.