@sigx/use
Prerequisites
Before continuing, make sure you're familiar with: Signals, Effects & scopes, Components
@sigx/use is a collection of small, tree-shakable composables built directly on the SignalX reactive core. Toggles and counters, debounced and throttled signals, timers, element sensors, storage, clipboard, media queries: each is an ordinary function you call from a component's setup, and each returns plain signals you read as values.
Here's the shape of it — a clamped counter in three lines:
import { component, render } from 'sigx';
import { useCounter } from '@sigx/use';
const Counter = component(() => {
const { count, inc, dec, reset } = useCounter(0, { min: 0, max: 10 });
return () => (
<div class="flex items-center gap-3">
<button class="btn" onClick={() => dec()}>-</button>
<span class="text-xl font-bold w-12 text-center">{count}</span>
<button class="btn" onClick={() => inc()}>+</button>
<button class="btn btn-ghost" onClick={() => reset()}>reset</button>
</div>
);
});
render(<Counter />, "#app");
No .value at the call site inside JSX, no manual subscriptions — count is a signal, and reading it in the render function re-renders the component. That's the whole ergonomic.
Two packages, one import for apps
@sigx/use ships as two packages so the same composables work on every SignalX target without dragging the DOM into places that don't have one:
| Package | Runs on | Contains |
|---|---|---|
@sigx/use | web, Lynx, SSR, terminal — statically DOM-free | The cross-platform composables (state, timing, debounce/throttle, shared state, utilities). |
@sigx/use-web | the browser (but SSR-safe) | The DOM/BOM sensors (elements, viewport, storage, clipboard, …) plus a re-export of all of @sigx/use. |
Because @sigx/use-web re-exports the core package, a web app installs one package and imports everything from it:
pnpm add @sigx/use-web// a web app: both cross-platform and browser composables from one entry
import { useCounter, useStorage, useMouse } from '@sigx/use-web';
A library or a non-web platform (Lynx, terminal) that only needs the DOM-free composables installs the core package directly:
pnpm add @sigx/useThroughout these docs, cross-platform composables show from '@sigx/use' and browser composables show from '@sigx/use-web' — but in a web app you can import both from @sigx/use-web.
Peers. Both packages peer-depend on
@sigx/reactivityand@sigx/runtime-core^0.13.0(thesigxumbrella your app already runs on provides these).@sigx/use-webadditionally peers@sigx/use. They never bundle their own copy of the core — a composable always shares the same reactive runtime as your components.
The cleanup model
Every composable that starts ongoing work — a timer, an event listener, an observer — cleans up on its own when the owning scope disposes. "Owning scope" means the component you called it in, or the innermost effectScope() if you're outside a component. Call useIntervalFn in a component and the interval clears on unmount; you write nothing.
For standalone use — outside any component or scope, in a script or a test — there's no scope to hook, so every such composable also returns an explicit handle: a stop() function, or a Pausable (pause/resume/isActive). Hold it and call stop() yourself.
import { useIntervalFn } from '@sigx/use';
// in a component: auto-clears on unmount
const { pause, resume } = useIntervalFn(() => tick(), 1000);
// standalone: you own teardown
const timer = useIntervalFn(() => tick(), 1000);
// ... later
timer.pause();
This is the same tryOnScopeDispose mechanism the composables use internally, and one you can reuse in your own.
What's deliberately not here
@sigx/use stays focused on device, UI, and reactivity utilities. A few neighbours own their space, and these docs point you at them rather than duplicating:
- Async data / server state → core's
useData/useAction.createGlobalStatehere is for device/UI state, not per-user data. - URL query params → the router's
useQuery. - Per-user, structured app state →
@sigx/store.
Building a platform pack
@sigx/use-web is the reference platform pack: it implements the web side of the shared contracts (StorageLike, NetworkState, ColorScheme, …) and re-exports the core package. @sigx/use-lynx and third-party packs follow the same recipe — implement the platform contracts, re-export the seam, peer-depend on @sigx/use, and pull shared helpers from the @sigx/use/internals subpath. See Conventions → Cross-platform contracts for the type surface a pack fulfils.
Next steps
- Conventions —
MaybeSignal,toValue,ReadSignal, reactive-view returns, element targets, and the cross-platform contracts. Read this next — it explains patterns every composable shares. useToggle,useCounter— start with the state composables.useStorage— the flagship: a deep-reactive object that auto-persists.
