Getting started
Install and use @kamod-ch/signals in a Preact app.
Getting started#
Get from zero to a working persisted signal in a few minutes.
Best first path: start with
localstorage, get one example working, then switch storage only if your use case needs it.
Install#
pnpm add @kamod-ch/signals @preact/signals preact
1) Create your first persisted signal#
Use persistedSignal() when the signal should be shared across files.
import { persistedSignal } from "@kamod-ch/signals";
export const theme = persistedSignal("theme", "dark", { storage: "local" });
Use it like any other Preact signal:
<button onClick={() => (theme.value = theme.value === "dark" ? "light" : "dark")}>
Theme: {theme.value}
</button>
What happens here:
- the value starts as
"dark" - updates are written to
localStorage - the same
storage + keyreturns the same global signal
2) Use the hook inside a component#
Use usePersistedSignal() when you want the same persistence behavior directly inside a component.
import { usePersistedSignal } from "@kamod-ch/signals";
function SidebarToggle() {
const isOpen = usePersistedSignal("sidebar-open", true, { storage: "session" });
return <button onClick={() => (isOpen.value = !isOpen.value)}>{String(isOpen.value)}</button>;
}
A good default split is:
persistedSignal()for app-wide shared stateusePersistedSignal()for component-local usage
3) Pick the right storage#
| Storage | Best for | Notes |
|---|---|---|
local |
preferences and UI settings | good default for theme, layout, dismissed UI |
session |
per-tab state | resets when the tab closes |
indexeddb |
larger client-side data | hydrates asynchronously |
cookie |
SSR-visible values | use when the server also needs the value |
memory |
fallback or ephemeral state | no browser persistence |
Quick decision: use
localfor preferences,sessionfor tab state,cookiefor SSR-visible values, andindexeddbfor larger data.
4) When to use cookie SSR#
Use storage: "cookie" with cookieContext only when the server must read or write the value during SSR.
import { createCookieContext, persistedSignal } from "@kamod-ch/signals";
const cookieContext = createCookieContext({
cookie: request.headers,
onSetCookie: (header) => response.headers.append("set-cookie", header),
});
const locale = persistedSignal("locale", "en", {
storage: "cookie",
cookieContext,
cookie: { path: "/", sameSite: "Lax" },
});
If the server does not need the value, prefer local or session.
Common first use cases#
- theme preference
- sidebar open/closed state
- locale hints for SSR
- drafts or cached data in IndexedDB
Common gotchas#
- IndexedDB starts with
initialValueand updates after hydration completes. persistedSignal()is global by identity, so reuse the same key with the same effective options.- Different SSR
cookieContextvalues stay isolated per request.
Next steps#
- Read the API overview for
sync, custom serialization, cookie settings, and runtime rules. - Explore the storage showcase to compare all drivers in one place.
- Review cookie SSR if the server must also read the value.