--- title: Resources description: Define resources, pass props, and host them. --- A **resource** is a self-contained unit of reactive state and logic: like a React component, but without UI. ## Defining a resource A resource body **is a hook**: a function that calls the React hooks you know, imported from `"react"`. Write it as a `use`-prefixed hook, then pass it to `resource()` to turn it into a Resource. ```ts import { resource } from "@assistant-ui/tap"; import { useState } from "react"; const useCounter = (props: { initialValue?: number }) => { const [count, setCount] = useState(props.initialValue ?? 0); return { count, increment: () => setCount((c) => c + 1) }; }; const Counter = resource(useCounter); ``` `resource()` turns a hook into a Resource, and [`useResource`](#hosting-a-resource) turns it back into a hook call. Keep the body in a `use`-prefixed binding: it gives the resource a stable identity for keys and devtools, and lets React's rules-of-hooks lint the body. `resource()` returns a **factory function**. Calling the factory creates a `ResourceElement`, a lightweight description of what to render, not a live instance yet. ### Resource elements A `ResourceElement` is a plain `{ hook, args }` object, the same idea as a React JSX element, but written as a function call instead of JSX. ```ts const element = Counter({ initialValue: 10 }); // { hook: useCounter, args: [{ initialValue: 10 }] } ``` Calling the factory (`Counter({ ... })`) reads like the plain function call it is. Like a JSX element, the result is inert until you host it. ### Props Resources accept props like components do. When a resource re-renders with new props, hooks react to the change through their dependency arrays, exactly as in React. ### Return value Instead of JSX, a resource returns any JavaScript value: an object, array, or primitive. That return value is the resource's public API, and it is what callers read when they host it. ## Hosting a resource `useResource` hosts a single element, re-entering the Resource as a hook call. It works the same way in both worlds: inside a React component it ties the resource to the component's lifecycle, and inside another resource it nests the resource as a child. ```tsx import { useResource } from "@assistant-ui/tap"; function CounterButton() { const { count, increment } = useResource(Counter({ initialValue: 10 })); return ; } ``` Unlike React, a parent reads its child's return value directly, which makes composition a tool for building up state and logic, not just trees. ```ts import { resource, useResource } from "@assistant-ui/tap"; const useDashboard = () => { const counter = useResource(Counter({ initialValue: 0 })); return { total: counter.count }; }; const Dashboard = resource(useDashboard); ``` ## Next - [Composition](/tap/docs/tap/composition): render keyed lists with `useResources` and expose subscribable boundaries with `useTapRoot`. - [Context](/tap/docs/tap/context): pass values through the resource tree without prop drilling.