use-truapi
Host

useHostStorage

Product-scoped JSON key-value storage with a standalone fallback

useHostStorage reads and writes a product-scoped key-value store. It returns a query result whose data is the JSON-parsed value (T | null, null when the key is unset), extended with two writers: set(value) serializes and persists, remove() deletes the key.

The backing store follows the environment: host localStorage inside a container (persisted by the host, scoped to your product), browser localStorage standalone. The hook behaves identically in both, making this one of the few host APIs that needs no gating.

The value is live. Inside a host the hook subscribes to the key (LocalStorage.subscribe), so a write or clear by any of the product's runtimes, a background worker included, shows up without a refetch; on hosts that predate the subscription it degrades to a one-shot read. Standalone it follows the browser's cross-tab storage event. Your own writes update the cached value in place as well, so every component reading the same key sees the new value immediately, with no flicker. Values are JSON round-tripped: store plain serializable data (no bigint, Date or Uint8Array).

Usage

Type the stored value with the generic parameter to get a typed data and a typed set.

import { useHostStorage } from "@use-truapi/react";

interface Settings {
  currency: "USD" | "EUR";
  compactMode: boolean;
}

const DEFAULTS: Settings = { currency: "USD", compactMode: false };

function SettingsPanel() {
  const { data, isPending, set, remove } = useHostStorage<Settings>("settings");
  const settings = data ?? DEFAULTS;

  if (isPending) return <p>Loading settings…</p>;

  return (
    <form>
      <label>
        <input
          type="checkbox"
          checked={settings.compactMode}
          onChange={(e) => void set({ ...settings, compactMode: e.target.checked })}
        />
        Compact mode
      </label>
      <button type="button" onClick={() => void remove()}>
        Reset to defaults
      </button>
    </form>
  );
}
<script setup lang="ts">
import { useHostStorage } from "@use-truapi/vue";
import { computed } from "vue";

interface Settings {
  currency: "USD" | "EUR";
  compactMode: boolean;
}

const DEFAULTS: Settings = { currency: "USD", compactMode: false };

const { data, isPending, set, remove } = useHostStorage<Settings>("settings");
const settings = computed(() => data.value ?? DEFAULTS);

function toggleCompact(event: Event) {
  const checked = (event.target as HTMLInputElement).checked;
  void set({ ...settings.value, compactMode: checked });
}
</script>

<template>
  <p v-if="isPending">Loading settings…</p>
  <form v-else>
    <label>
      <input type="checkbox" :checked="settings.compactMode" @change="toggleCompact" />
      Compact mode
    </label>
    <button type="button" @click="remove()">Reset to defaults</button>
  </form>
</template>

The key can be a getter (() => "draft:" + props.id); the query re-runs and the writers retarget when it changes.

See also

API reference

React

function useHostStorage<T>(key, options?): HostStorageValue<T>;

Product-scoped KV storage, live: host localStorage inside a container (LocalStorage.subscribe, so writes from the product's other runtimes show up), browser localStorage standalone (following the cross-tab storage event). JSON-serialized. Writes update the query cache in place under queryKeys.hostStorage(key).

Type Parameters

Type Parameter
T

Parameters

ParameterType
keystring
options?{ query?: QueryOptions<T | null>; }
options.query?QueryOptions<T | null>

Returns

HostStorageValue<T>

type HostStorageValue<T> = UseQueryResult<T | null, Error> & object;

Type Declaration

remove

remove: () => Promise<void>;
Returns

Promise<void>

set

set: (value) => Promise<void>;
Parameters
ParameterType
valueT
Returns

Promise<void>

Type Parameters

Type Parameter
T

Vue

function useHostStorage<T>(key, options?): HostStorageValue<T>;

Product-scoped KV storage, live: host localStorage inside a container (LocalStorage.subscribe, so writes from the product's other runtimes show up), browser localStorage standalone (following the cross-tab storage event). JSON-serialized. Writes update the query cache in place under queryKeys.hostStorage(key).

Type Parameters

Type Parameter
T

Parameters

ParameterType
keyMaybeGetter<string>
options?{ query?: QueryOptions<T | null>; }
options.query?QueryOptions<T | null>

Returns

HostStorageValue<T>

type HostStorageValue<T> = QueryResult<T | null> & object;

Type Declaration

remove

remove: () => Promise<void>;
Returns

Promise<void>

set

set: (value) => Promise<void>;
Parameters
ParameterType
valueT
Returns

Promise<void>

Type Parameters

Type Parameter
T

On this page