useNodeControls
useNodeControls(spec, args) returns the runtime operations for a node without reading its result. The component does not subscribe to the node’s data, so it never suspends. Use it for a control — a refresh button, a “sign out” that evicts — that acts on a node it does not render.
import * as FrondReact from "@frondruntime/react";
function RefreshButton({ userId }: { userId: string }) {
const controls = FrondReact.useNodeControls(ProfileNode, { userId });
return <button onClick={() => void controls.refresh()}>Reload</button>;
}
No observer needed — useNodeControls reads no observable fields.
Returns
| Member | Type | Description |
|---|---|---|
nodeId | NodeId | The graph node id. |
ensureReady | () => Promise<void> | Acquire and wait until ready. |
refresh | () => Promise<RefreshResult> | Re-acquire while keeping current data visible. |
evict | (mode?, reason?) => Promise<EvictResult> | Remove from the graph. Default mode "selfAndDependents". |
releaseResources | (reason?) => Promise<void> | Tear down resources, keep the wiring. |
These map to the runtime handle. See Eviction and release and Lifecycle.
Controls, not product behavior
useNodeControls covers runtime operations — refresh, evict, release. For product behavior like renaming or saving, call a node action on the instance you read with useNode instead. Actions commit results and carry typed input and output.
Multiple nodes
useNodesControls takes a map of { key: [Spec, args] } and returns controls per key.
const controls = FrondReact.useNodesControls({
profile: [ProfileNode, { userId }],
billing: [BillingNode, { userId }],
});
controls.profile.refresh();
controls.billing.evict();
The map’s key set must be stable across renders.
Next: Preload — acquire nodes before a subtree renders.