# React Hooks

Provider, auth, analytics, and WebRTC hooks from @agentuity/react

This page covers the `@agentuity/react` package. If you are maintaining code that already uses it, these hooks still work. For new apps, prefer `hc()` for route calls, `@agentuity/auth/react` for auth state, and `@agentuity/frontend` for browser-level utilities.

> [!WARNING]
> **@agentuity/react Is Deprecated**
> This package is deprecated. Keep using it only when you already rely on `AgentuityProvider`, `useWebRTCCall()`, or the compatibility hooks documented here.

> [!TIP]
> **Route Calls Use hc()**
> `@agentuity/react` does not ship a generated route client. Export your router type from `src/api/index.ts` and call routes with `hc<ApiRouter>()`. See [RPC Client](/frontend/rpc-client) for the full pattern.

## Installation

```bash
bun add @agentuity/react
```

## Calling API Routes

Use `hc()` from `hono/client` for type-safe route calls, or plain `fetch` for simple cases:

```tsx
import { hc } from 'hono/client';
import type { ApiRouter } from '../api/index';
import { useState } from 'react';

const client = hc<ApiRouter>('/api');

function ChatForm() {
  const [data, setData] = useState<{ response: string } | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<Error | null>(null);

  const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    const formData = new FormData(e.currentTarget);
    const message = formData.get('message') as string;

    setIsLoading(true);
    setError(null);
    try {
      const res = await client.chat.$post({ json: { message } });
      setData(await res.json());
    } catch (err) {
      setError(err instanceof Error ? err : new Error(String(err)));
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input name="message" placeholder="Type a message..." disabled={isLoading} />
      <button type="submit" disabled={isLoading}>
        {isLoading ? 'Sending...' : 'Send'}
      </button>
      {error && <p>Error: {error.message}</p>}
      {data && <p>Response: {data.response}</p>}
    </form>
  );
}
```

Or with plain `fetch`:

```tsx
const res = await fetch('/api/chat', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ message }),
});
const data = await res.json();
```

## Reading Provider State with useAgentuity

Use `useAgentuity()` when you need the resolved backend URL inside your own helpers or components:

```tsx
import { useAgentuity } from '@agentuity/react';

function ApiBaseBadge() {
  const { baseUrl } = useAgentuity();

  return <code>{baseUrl}</code>;
}
```

This is useful when your frontend and Agentuity app live on different origins and you want to build an absolute `hc()` client or show which backend you are connected to.

## Transport Auth with useAuth

Use `useAuth()` from `@agentuity/react` to read the transport auth state managed by `AgentuityProvider`:

```tsx
import { useAuth } from '@agentuity/react';

function ProtectedBanner() {
  const { isAuthenticated, authLoading } = useAuth();

  if (authLoading) {
    return <p>Loading...</p>;
  }

  if (!isAuthenticated) {
    return <p>Please sign in to continue.</p>;
  }

  return <p>Authenticated and ready to call protected routes.</p>;
}
```

**Return values:**

| Property | Type | Description |
|----------|------|-------------|
| `isAuthenticated` | `boolean` | True when auth token is set and not loading |
| `authLoading` | `boolean` | True while auth state is initializing |
| `authHeader` | `string \| null` | The current Authorization header value |
| `setAuthHeader` | `(token: string \| null) => void` | Manually set the auth header |
| `setAuthLoading` | `(loading: boolean) => void` | Control the loading state |

> [!NOTE]
> **Two Different useAuth Hooks**
> `@agentuity/react` and `@agentuity/auth/react` both export `useAuth()`. The React package exposes the transport auth header used by Agentuity helpers. The auth package exposes signed-in user and session state. Alias the imports when you use both in the same file.

## WebRTC with useWebRTCCall

Use `useWebRTCCall()` for peer-to-peer audio, video, and data channels:

```tsx
import { useWebRTCCall } from '@agentuity/react';

function CallPanel({ roomId }: { roomId: string }) {
  const {
    state,
    localVideoRef,
    connect,
    hangup,
    isAudioMuted,
    muteAudio,
  } = useWebRTCCall({
    roomId,
    signalUrl: '/api/call/signal',
    autoConnect: false,
  });

  return (
    <div>
      <video ref={localVideoRef} autoPlay muted playsInline />
      <p>State: {state}</p>
      <button onClick={connect}>Join</button>
      <button onClick={() => muteAudio(!isAudioMuted)}>
        {isAudioMuted ? 'Unmute' : 'Mute'}
      </button>
      <button onClick={hangup}>Leave</button>
    </div>
  );
}
```

For signaling routes, rooms, data channels, and media options, see [WebRTC](/routes/webrtc).

## Analytics Hooks

Track page views and custom events from React components. See [Web Analytics](/services/observability/web-analytics) for configuration, privacy options, and the full API.

```tsx
import { useAnalytics, useTrackOnMount } from '@agentuity/react';

function ProductPage({ productId }: { productId: string }) {
  const { track, trackClick } = useAnalytics();

  // Fires once when the component mounts
  useTrackOnMount({
    eventName: 'product_viewed',
    properties: { productId },
  });

  return (
    <button onClick={trackClick('add_to_cart', { productId })}>
      Add to Cart
    </button>
  );
}
```

A `withPageTracking` HOC is also available for class components or simpler page-level tracking.

## Real-Time Communication

Use the transport that matches the route you are calling:

| Pattern | API | Use Case |
|---------|-----|----------|
| Bidirectional streaming | `WebSocket` | Live chat, collaboration |
| Server push | `EventSource` | AI streaming, live dashboards |
| Peer-to-peer | `useWebRTCCall` | Video/audio calls, data channels |
| Request/response | `hc()` or `fetch` | API calls, form submissions |

See [WebSockets](/routes/websockets), [SSE](/routes/sse), and [WebRTC](/routes/webrtc) for server-side setup.

## Next Steps

- [Provider Setup](/frontend/provider-setup): `AgentuityProvider` configuration for existing apps
- [Advanced Hooks](/frontend/advanced-hooks): `WebSocketManager` and `EventStreamManager` from `@agentuity/frontend`
- [RPC Client](/frontend/rpc-client): Type-safe API calls with `hc()`
- [Web Analytics](/services/observability/web-analytics): Track page views and custom events