React
RectProvider and the hooks.
@rectsh/rect/react binds the store to React with useSyncExternalStore, so
reads are concurrent-safe and components re-render only when their slice
changes.
Provider
Wrap your view in RectProvider. It connects to the host and gates children
until ready, so the hooks below never see a half-connected store.
import { RectProvider } from '@rectsh/rect/react';
<RectProvider
fallback={<p>Connecting…</p>}
errorFallback={(err) => <p>{err.message}</p>}
>
<View />
</RectProvider>;Pass store to inject a store directly (see Testing).
Reading
import { useRectState, useRectValue } from '@rectsh/rect/react';
// The whole view model — re-renders on any change.
const state = useRectState<Note>();
// A derived slice — re-renders only when it changes (Object.is, or your isEqual).
const count = useRectValue<Note, number>((s) => s.items.length);Writing
import { useRectField, useRectActions } from '@rectsh/rect/react';
// Two-way binding for one path — great for inputs.
function TitleInput() {
const [title, setTitle] = useRectField<string>('title');
return (
<input value={title ?? ''} onChange={(e) => setTitle(e.target.value)} />
);
}
// Stable action handles for callbacks.
function Approve() {
const { patch } = useRectActions();
return <button onClick={() => patch({ approved: true })}>Approve</button>;
}Dispatching actions
When the view defines named actions, useRectDispatch()
runs them — the handler executes host-side, and a business rejection comes
back as a value, not an exception:
import { useRectDispatch } from '@rectsh/rect/react';
function Approve() {
const dispatch = useRectDispatch();
return (
<button
onClick={async () => {
const result = await dispatch('approve');
if (!result.ok) showToast(result.message ?? result.code);
}}
>
Approve
</button>
);
}Everything
| Hook | Returns |
|---|---|
useRectState<T>() | The whole view model (subscribed). |
useRectValue(selector, isEqual?) | A derived slice (subscribed). |
useRectField<V>(path) | [value, setValue] for one path. |
useRectActions<T>() | Stable { set, update, patch }. |
useRectDispatch() | (action, input?) => Promise<RectDispatchResult>. |
useRect() | The raw store (escape hatch). |
useRectRevision() | The current revision (subscribed). |
useRectMeta() | The static host metadata. |
Full signatures are in the generated API reference.