v0 · Developer Preview Frond is under active development. APIs may change between releases.

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

MemberTypeDescription
nodeIdNodeIdThe 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.