> ## Documentation Index
> Fetch the complete documentation index at: https://docs.metabind.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Hooks

> A concept-level index of the runtime-injected functions a BindJS component body can call

Hooks are runtime-injected functions a component body can call to read context, manage state, navigate, dispatch host actions, or talk to an MCP host. Six are part of the core surface: `useState`, `useStore`, `useEnvironment`, `useNavigate`, `useAction`, and `useMCPHost`. This page is a concept-level index — each section explains when to reach for a hook and links to its reference page for the full signature.

## `useState`

Component-local state. Each component instance maintains its own state across re-renders, keyed by the component's deterministic position in the tree.

```typescript theme={null}
const [count, setCount] = useState(0)
```

Reach for `useState` when the value belongs to one component — a toggle, a draft input, a hover flag. See [`useState`](/bindjs/functions/useState) for the reference, and [State and environment](/bindjs/authoring/state) for the broader story.

## `useStore`

Shared state, keyed by name and optionally scoped. Returns a store with flattened fields, auto-generated per-field setters, and a `set` method for full-state updates.

```typescript theme={null}
const store = useStore("counter", { count: 0, label: "clicks" })
store.setCount(store.count + 1)
```

Reach for `useStore` when several components need to read or write the same value — filter state, a cart, a multi-step form. See [`useStore`](/bindjs/functions/useStore) for the reference.

## `useEnvironment`

Reads the current environment values — the keys a runtime injects (color scheme, locale, content size, and the rest) plus any values set by ancestor components via `.environment(key, value)`.

```typescript theme={null}
const env = useEnvironment()
const isDark = env.colorScheme === "dark"
```

Reach for `useEnvironment` to adapt a component to context an ancestor or the host has set. Always provide a fallback for keys that may not be present. See [`useEnvironment`](/bindjs/functions/useEnvironment) for the reference.

## `useNavigate`

Returns a navigation function for programmatic navigation. The host app defines how a navigate call is handled — push, route change, modal, or platform-specific equivalent.

```typescript theme={null}
const navigate = useNavigate()
navigate({ to: "DetailView", props: { id: "123" } })
```

Reach for `useNavigate` from event handlers — a button tap that should move the user, a row tap that opens a detail screen. See [`useNavigate`](/bindjs/functions/useNavigate) for the reference.

## `useAction`

Returns an action dispatch function for triggering host-app-defined actions. Use it for analytics, deep links, or native integrations the host registers.

```typescript theme={null}
const action = useAction()
action({ name: "addToCart", props: { productId: "abc" } })
```

Reach for `useAction` when you need the host to do something that is not navigation and not state — fire an analytics event, open a system share sheet, run a registered native handler. See [`useAction`](/bindjs/functions/useAction) for the reference.

## `useMCPHost`

Returns the MCP host interface when the BindJS view is rendered inside an MCP host (a sandboxed iframe in Claude or ChatGPT, or natively via the Assistant SDK). Returns `null` when no host bridge is available.

```typescript theme={null}
const host = useMCPHost()
host?.toolCall("get_product", { id: props.productId }).then(setProduct)
```

Reach for `useMCPHost` when a component needs to call back into the chat — invoking another tool, sending a message, updating model context, or asking the host to change display mode. The hook is registered on every conforming runtime; whether it returns a live bridge depends on where the component is rendered. See [MCP host bridge](/bindjs/authoring/mcp-host) for the deep treatment, including the full interface, the fetch-on-mount pattern, and end-to-end examples.

## Hook rules

Two rules carry across every hook. Both come from how the runtime keys state by tree position:

* **Hooks must not be called conditionally.** Every hook call has to run on every render. Wrapping a hook in `if (cond)` desyncs the indices and corrupts state. Declare the hook at the top of the body and gate the use, not the call.
* **Items in a dynamic list need a stable `.id(...)`.** A runtime keys child state by tree position; without a stable identity, reordering or inserting items reassigns state to the wrong child.

```typescript theme={null}
ForEach(items, (item) =>
    ProductCard({ name: item.name }).id(item.id)
)
```

Both rules come from how the runtime keys component state by tree position. See [State and environment](/bindjs/authoring/state) for the full treatment.

## What to read next

<CardGroup cols={2}>
  <Card title="State and environment" icon="circle-nodes" href="/bindjs/authoring/state">
    How `useState`, `useStore`, and environment values fit together.
  </Card>

  <Card title="MCP host bridge" icon="plug" href="/bindjs/authoring/mcp-host">
    The full `useMCPHost` interface — tool calls, messaging, display mode, and the fetch-on-mount pattern.
  </Card>

  <Card title="Composition and slots" icon="layer-group" href="/bindjs/authoring/composition">
    How component names resolve and how layouts declare child slots.
  </Card>

  <Card title="useState" icon="circle-info" href="/bindjs/functions/useState">
    The hook reference for component-local state.
  </Card>
</CardGroup>
