# React

> Use the widgets as React components, or build your own interface with the useVoxioSession hook.

Source: https://voxio.in/docs/react · voxioagent 2.0.0 · Index: https://voxio.in/docs/llms.txt

`voxioagent/react` works with React 18 and later.

## Use the components

Each widget is a component. Its props are the widget's options, plus `className`, `style`, `id` and three event props:

```jsx
import { VoxioVoiceButton } from "voxioagent/react";

<VoxioVoiceButton
  flowKey="YOUR_FLOW_KEY"
  label="Talk to us"
  onStateChange={(state, muted) => {}}
  onError={(error) => console.warn(error.code)}
  onEnded={({ reason, seconds, sessionId }) => {}}
  elementRef={(el) => el?.attach(document.querySelector("#cta"))}
/>
```

Replace `YOUR_FLOW_KEY` with your flow key, from the flow's **Overview** in the dashboard.

`elementRef` gives you the underlying element, for methods such as `attach()` and `open()`. The other components are `VoxioAvatar` and `VoxioChat`.

## Build your own interface

The `useVoxioSession` hook gives you a session tied to the component's lifetime. This component shows the state, a level meter and the controls:

Call.jsx:

```jsx
import { useVoxioSession } from "voxioagent/react";

export function Call() {
  const v = useVoxioSession({ flowKey: "YOUR_FLOW_KEY" });

  return (
    <div>
      <p>{v.state}</p>
      <meter value={v.level.agent} />
      {v.error && <p>{v.error.code}</p>}
      <button onClick={v.start} disabled={!v.session}>Start</button>
      <button onClick={() => v.mute(!v.muted)}>{v.muted ? "Unmute" : "Mute"}</button>
      <button onClick={v.stop}>End</button>
    </div>
  );
}
```

After you click **Start**, the state moves to `connecting`, then `listening`, and the meter moves when the agent speaks. The hook returns:

| Field | What it is |
| --- | --- |
| `session` | The underlying `VoxioSession`, or `null` until the component mounts. |
| `state` | `idle`, `connecting`, `listening`, `speaking`, `ended` or `error`. |
| `muted` | Whether the microphone is muted. |
| `error` | The last `VoxioError`, or `null`. |
| `level` | `{ user, agent }`, each from 0 to 1, updated about 20 times a second. |
| `agentStream` | The avatar video, when `media.video` is on. |
| `start()` and `stop()` | Start or end the call. Call start from a click or tap. |
| `mute(muted?)` | Mutes or unmutes the microphone. |

> **Note: Options are read once**
>
> The hook reads its options when the component mounts. To change them, remount the component, for example by giving it a new `key`.

## Render on the client

Sessions use browser APIs. With Next.js, Remix or TanStack Start, render these components on the client only, for example with `React.lazy` or a client-only boundary.

## Next steps

- [Headless sessions](https://voxio.in/docs/sessions.md): see every session option and event.
- [Errors](https://voxio.in/docs/errors.md): handle each error code.
