Documents
api-reference
api-reference
Type
External
Status
Published
Created
Mar 17, 2026
Updated
Mar 17, 2026

resource#

Creates a resource factory function.

import { resource } from "@assistant-ui/tap";

const Counter = resource((props: { initialValue: number }) => {
  const [count, setCount] = tapState(props.initialValue);
  return { count, increment: () => setCount((c) => c + 1) };
});

Returns a factory function — calling it produces a ResourceElement.

withKey#

Attaches a key to a ResourceElement for identity preservation in lists.

import { withKey } from "@assistant-ui/tap";

withKey("my-key", Counter({ initialValue: 0 }))

Hooks#

All hooks follow the rules of hooks.

tapState#

const [value, setValue] = tapState(initialValue);
const [value, setValue] = tapState(() => expensiveDefault());

Local state. setValue accepts a value or an updater function (prev) => next.

tapReducer#

const [state, dispatch] = tapReducer(reducer, initialState);
const [state, dispatch] = tapReducer(reducer, initialArg, init);

State management with a reducer function. dispatch has a stable identity. Bails out (no re-render) when the reducer returns the same state via Object.is.

tapReducerWithDerivedState#

This API is experimental, intended for advanced use cases, and may change.
const [state, dispatch] = tapReducerWithDerivedState(reducer, getDerivedState, initialState);
const [state, dispatch] = tapReducerWithDerivedState(reducer, getDerivedState, initialArg, init);

Like tapReducer, but accepts a getDerivedState function as the second argument. During each render pass, getDerivedState(state) is called once after processing any queued actions. If it returns a new value (by Object.is), the derived value becomes the current state and triggers a re-render. The return type is inferred from getDerivedState, allowing you to narrow or extend the state type.

tapEffect#

tapEffect(() => {
  // side effect
  return () => { /* cleanup */ };
}, [deps]);

Runs after commit. Without a dependency array, runs after every render.

tapMemo#

const value = tapMemo(() => compute(a, b), [a, b]);

Memoizes a value. Recomputes when dependencies change.

tapCallback#

const fn = tapCallback(() => { /* ... */ }, [deps]);

Memoizes a function. Shorthand for tapMemo(() => fn, deps).

tapRef#

const ref = tapRef(initialValue);
ref.current; // read/write

A mutable ref that persists across renders.

tapConst#

const value = tapConst(() => new EventEmitter(), []);

Computed once on mount, never recomputed. The second argument must always be [].

tapEffectEvent#

const handler = tapEffectEvent((msg: string) => {
  // always has access to latest closure
});

Returns a stable function reference that always calls the latest version of the callback. Useful for event handlers passed to effects.


Composition hooks#

tapResource#

const value = tapResource(Counter({ initialValue: 0 }));
const value = tapResource(Counter({ initialValue }), [initialValue]);

Renders a single child resource. Returns the child's return value.

The optional dependency array controls when new props are applied.

The dependency array API is experimental and may change.

tapResources#

This API is experimental and may change.
const values = tapResources(
  () => items.map((item) => withKey(item.id, TodoItem({ text: item.text }))),
  [items],
);

Renders a dynamic list of child resources. Every element must have a key via withKey.

tapResourceRoot#

const handle = tapResourceRoot(Counter({ initialValue: 0 }));

handle.getValue(); // current value
handle.subscribe(() => { /* on change */ });

Renders a child as a subscribable store. The parent doesn't re-render when the child updates.


Imperative API#

createResourceRoot#

Creates a resource instance outside of React.

import { createResourceRoot } from "@assistant-ui/tap";

const root = createResourceRoot();
const handle = root.render(Counter({ initialValue: 0 }));

Root methods:

MethodDescription
root.render(element)Render (or re-render) with a resource element. Returns a subscribable handle.
root.unmount()Unmount and clean up

Subscribable handle methods (returned by root.render()):

MethodDescription
handle.getValue()Read the current return value
handle.subscribe(callback)Subscribe to changes

flushResourcesSync#

Synchronously flushes pending tap scheduler updates.

import { flushResourcesSync } from "@assistant-ui/tap";

flushResourcesSync(() => {
  handle.getValue().increment();
});
// state is already updated here

Only applies to tap-scheduled trees (createResourceRoot / tapResourceRoot). For useResource trees, use flushSync from react-dom.


Context#

The context API is experimental and may change significantly.

createResourceContext#

import { createResourceContext } from "@assistant-ui/tap";

const ThemeContext = createResourceContext("light");

Creates a context with a default value.

tap#

import { tap } from "@assistant-ui/tap";

const theme = tap(ThemeContext);

Reads the current value of a context inside a resource.

withContextProvider#

import { withContextProvider } from "@assistant-ui/tap";

const child = withContextProvider(ThemeContext, "dark", () => {
  return tapResource(Button());
});

Provides a context value to all resources rendered within the callback.


React#

useResource#

import { useResource } from "@assistant-ui/tap/react";

const { count, increment } = useResource(Counter({ initialValue: 0 }));

Binds a resource to a React component's lifecycle. The component re-renders when the resource's state changes.


Types#

Resource#

type Resource<R, P> = (props: P) => ResourceElement<R, P>;

The factory function returned by resource().

ResourceElement#

type ResourceElement<R, P> = { type: Resource<R, P>; props: P; key?: string | number };

A lightweight { type, props } description of a resource to render.

ContravariantResource#

type ContravariantResource<R, P> = (props: P) => ResourceElement<R>;

A contravariant version of Resource for type-level flexibility when accepting resources as parameters. The difference from Resource is that the returned ResourceElement omits the P type parameter, allowing broader assignability.