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

# React hooks

These hooks are exported by `@napps/nodes`. Use them only inside a React UI component created by `BaseReactUIComponent` or `createReactUIComponent`.

## Runtime and context hooks

### `useComponentRuntime`

Returns the complete runtime value:

```ts theme={null}
const runtime = useComponentRuntime();
// runtime.componentContext
// runtime.args
// runtime.subscribe(event, listener)
```

It throws when called outside a NAPPS React component.

### `useComponentContext`

Returns the native `ComponentContext`. Use it when a component needs context services such as product cards or component lifecycle operations.

### `useComponentArgs<TSettings>`

Returns the component arguments, including the optional identifier, package name, and settings:

```ts theme={null}
const args = useComponentArgs<PromoSettings>();
```

### `useComponentSettings<TSettings>`

Returns `args.settings` directly. It is `undefined` when no settings were provided.

## Event hooks

### `useComponentEvent`

Subscribes to a named native component event and calls the latest callback without resubscribing on every render. The returned subscription is cleaned up automatically.

```tsx theme={null}
import { useState } from "react";
import { useComponentEvent } from "@napps/nodes";

function VariantStatus() {
  const [selectedVariantId, setSelectedVariantId] = useState<string | null>(null);

  useComponentEvent<{ matchingVariantMeta?: { id: string } }>(
    "productInfoChanged",
    (event) => {
      setSelectedVariantId(event.matchingVariantMeta?.id ?? null);
    }
  );

  return <text>{selectedVariantId ?? "No variant selected"}</text>;
}
```

### `useComponentEventState`

Stores the latest payload for a named event and returns it as React state:

```tsx theme={null}
const selected = useComponentEventState<SelectedPropertiesEventData>(
  "selectedPropertiesUpdated"
);
```

It returns the supplied initial value, or `null` by default, until the event fires.

## Product and PDP hooks

### `useSelectedProperties`

Tracks `selectedPropertiesUpdated` events. The value includes selected option values, the matching variant when available, and the quantity added to cart.

### `useProductInfo`

Tracks `productInfoChanged` events and returns the latest product information payload.

### `usePreferredStoresChanged`

Calls a callback when the preferred store IDs change:

```tsx theme={null}
usePreferredStoresChanged(({ preferredStoreIDs }) => {
  console.log(preferredStoreIDs);
});
```

## Product card hook

### `useProductCards`

Provides the product window for a `product-card-extension`:

```ts theme={null}
const { products, loadingCount, surface } = useProductCards();
```

* `products`: products in native display order.
* `loadingCount`: placeholder slots that must be rendered after real products.
* `surface`: the current surface name, or `null` when no card bridge is attached.

Product surfaces can append or slide their window. Render a flat root list and use stable keys so React preserves card identity while scrolling.

## Hook best practices

* Call hooks at the top level of a component.
* Keep event callbacks lightweight and update React state instead of mutating native nodes directly.
* Render nothing when `useProductCards().surface` is `null`.
* Render `loadingCount` skeletons after real product cards.
* Clean up custom subscriptions in `useEffect` when they are not managed by an Expresso hook.
