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

# Dictation SDK React Integration

> Integrate `@suki-sdk/dictation-react` with `DictationProvider` and `<Dictation>`: auth setup, client lifecycle, and in-field or scratchpad sessions

This guide shows how to integrate the Suki Dictation SDK into React applications using the `@suki-sdk/dictation-react` package. You'll initialize the `DictationClient`, provide it through the `DictationProvider`, and render the `Dictation` component to start Dictation sessions in your application.

Use this approach if you're building with React and want to integrate Dictation using React components and hooks instead of managing the interface programmatically.

Let's get started!

## Prerequisites

Before you begin, you must have the following requirements met:

* **Packages:** Install **`@suki-sdk/dictation-react`**, **`@suki-sdk/dictation`**, and **`@suki-sdk/core`**.
* **Partner credentials:** Obtain **`partnerId`** and **`partnerToken`** from Suki after [Partner onboarding](/documentation/get-started/partner-onboarding).
* **Browser and layout:** Your app runs in a **browser**, with a real DOM and enough layout for the Dictation UI.

Refer to [Prerequisites](/dictation-sdk/prerequisites) guide for more details.

## Install the packages

Add all three packages to the same project you load in the browser:

<CodeGroup title="Install @suki-sdk/dictation-react, @suki-sdk/dictation, @suki-sdk/core">
  ```shell pnpm theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
  pnpm add @suki-sdk/core @suki-sdk/dictation-react @suki-sdk/dictation 
  ```

  ```shell yarn theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
  yarn add @suki-sdk/core @suki-sdk/dictation-react @suki-sdk/dictation 
  ```

  ```shell npm theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
  npm install @suki-sdk/core @suki-sdk/dictation-react @suki-sdk/dictation 
  ```
</CodeGroup>

<Tip>
  After you install, pull the SDK into your files with **`import`**, the same way as in the examples below. Use whatever approach your project already uses for other npm libraries.
</Tip>

## Step 1: Add container and field layout

For this example we will assume you are using **`in-field`** mode as your preferred mode.

In **`in-field`** mode you need **two** parts in the UI: a **`div`** (or similar) that you can pass as **`rootElement`**, where the Dictation controls show up, and a **textarea** (or input) that **`onSubmit`** will update when the user finishes.

The Dictation layer **matches the size of** **`rootElement`** when you set it, so that node should have a **height** you control. Refer to [Wrapper layout](/dictation-sdk/guides/configuration#wrapper-layout) guide for recommended markup and CSS.

**Code example for container and field layout**

```jsx React  theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
<div id="clinical-notes-dictation-root" style={{ minHeight: 120 }} />
<label htmlFor="clinical-notes">Clinical notes</label>
<textarea id="clinical-notes" rows={8} />
```

Wire **`value`**, **`onChange`**, and your start button in the same component (see Step 5).

## Step 2: Create auth manager

Now you need to create the **Auth Manager** for your application. To create the Auth Manager, you must have the **`partnerId`** and **`partnerToken`** credentials from Suki.

Refer to [Partner onboarding](/documentation/get-started/partner-onboarding) guide to learn how to get these credentials.

In React you usually create the auth manager **inside** the same **`useMemo`** as the Dictation client (see Step 3), so both exist once per page or shell. The snippet below shows only the auth piece for clarity.

**Code example for creating auth manager**

```jsx React theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
import { SukiAuthManager } from "@suki-sdk/core";

const authManager = new SukiAuthManager({
  partnerId: "YOUR_PARTNER_ID", // replace with your partner ID - required
  partnerToken: "YOUR_PARTNER_TOKEN", // replace with your partner token - required
  environment: "staging", // optional: "staging" | "production"
  loginOnInitialize: true, // optional: sign in as soon as this runs
  autoRegister: false, // optional: enable provider auto-registration
  providerId: "YOUR_PROVIDER_ID", // optional: provider identifier in your system
  providerName: "YOUR_PROVIDER_NAME", // optional: full provider display name
  providerOrgId: "YOUR_PROVIDER_ORG_ID", // optional: organization identifier for the provider in your system
  providerSpecialty: "YOUR_PROVIDER_SPECIALTY", // optional: clinical specialty
});
```

## Step 3: Create Dictation client

After you have created the auth manager, you can create the **Dictation client** for your application. The Dictation Client is the object the React components use under the hood.

Create **one** Dictation client and reuse it for the whole tree under **`DictationProvider`**. Use **`useMemo`** with an empty dependency array so you do **not** run **`new DictationClient(...)`** on every render.

**Code example for creating Dictation client in React**

```jsx React expandable theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
import { useMemo } from "react";
import { SukiAuthManager } from "@suki-sdk/core";
import { DictationClient } from "@suki-sdk/dictation";

const client = useMemo(() => {
  const authManager = new SukiAuthManager({
    partnerId: "YOUR_PARTNER_ID", // replace with your partner ID - required
    partnerToken: "YOUR_PARTNER_TOKEN", // replace with your partner token - required
    environment: "staging", // optional: "staging" | "production"
    loginOnInitialize: true, // optional: sign in as soon as this runs
    autoRegister: false, // optional: enable provider auto-registration
    providerId: "YOUR_PROVIDER_ID", // optional: provider identifier in your system
    providerName: "YOUR_PROVIDER_NAME", // optional: full provider display name
    providerOrgId: "YOUR_PROVIDER_ORG_ID", // optional: organization identifier for the provider in your system
    providerSpecialty: "YOUR_PROVIDER_SPECIALTY", // optional: clinical specialty
  });
  return new DictationClient({ authManager });
}, []);
```

## Step 4: Wrap with DictationProvider

Pass the **`client`** from Step 3 into **`DictationProvider`**. Every component that renders **`<Dictation>`** must be a **child** of that provider.

**Code example for wrapping with DictationProvider**

```jsx React expandable theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
import { DictationProvider } from "@suki-sdk/dictation-react";

export function App() {
  const client = useMemo(/* ... Step 3 ... */, []);

  return (
    <DictationProvider client={client}>
      {/* children that render <Dictation /> */}
    </DictationProvider>
  );
}
```

You can put **`DictationProvider`** at app root or only around the screen that needs Dictation.

## Step 5: Render Dictation

Render **`<Dictation>`** only while that field should own the session (for example when the user clicked "Start Dictation"). When **`<Dictation>`** unmounts, the SDK calls **`hide()`** for you.

Pass **`mode`**, **`fieldId`**, **`initialText`**, **`onSubmit`**, and any optional props you need. Refer to [Configuration](/dictation-sdk/guides/configuration) guide for more details on the available options and how to use them.

**Code example for rendering Dictation in React**

```jsx React expandable theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
import { useState } from "react";
import { Dictation } from "@suki-sdk/dictation-react";

function NotesEditor() {
  const [notes, setNotes] = useState("");
  const [dictationActive, setDictationActive] = useState(false);

  return (
    <>
      <textarea
        id="clinical-notes"
        value={notes}
        onChange={(e) => setNotes(e.target.value)}
      />
      <button
        type="button"
        onClick={() => setDictationActive((v) => !v)}
      >
        {dictationActive ? "Stop dictation" : "Start dictation"}
      </button>
      {dictationActive && (
        <Dictation
          fieldId="clinical-notes"
          mode="in-field"
          initialText={notes}
          onSubmit={({ text }) => setNotes(text)}
          onCancel={() => setDictationActive(false)}
        />
      )}
    </>
  );
}
```

<Tip>
  You can also drive Dictation with a single **`activeFieldId`** string and render one **`<Dictation>`** when it matches, which scales to multiple fields.
</Tip>

<Note>
  **`onSubmit`** is required for a good user experience. If you omit it, Dictation often **closes immediately** after the user acts.
</Note>

## Callbacks

Props such as **`onSubmit`**, **`onCancel`**, and **`onDraft`** receive the same shape as in the JavaScript API:

```jsx React  theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
{ fieldId: string, 
text: string 
}
```

Refer to [Callbacks](/dictation-sdk/guides/callbacks) guide for more details on the available callbacks and how to use them.

<Note>
  You do not poll for text; the SDK calls your functions when the user commits or cancels, and may call **`onDraft`** when they move on without submitting (refer to [Callbacks](/dictation-sdk/guides/callbacks) guide for more details).
</Note>

## Switching fields

Use the same **`client`** and **`DictationProvider`**. Change which field is active by updating state (for example **`activeFieldId`**) so only one **`<Dictation>`** is mounted, or swap **`fieldId`** / **`initialText`** on the next mount. You do **not** need to call **`hide()`** yourself just to move from one field to another when unmounting one **`<Dictation>`** and mounting another is how your UI switches.

## Unmounting and hiding

When **`<Dictation>`** unmounts, the SDK **automatically** calls **`hide()`**. You do not need to call **`hide()`** yourself for normal React flows.

## Complete code example

Below is a complete code example in React for in-field mode with **`DictationProvider`**, a toggle button, and one field.

```jsx React theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
import { useMemo, useState } from "react";
import { SukiAuthManager } from "@suki-sdk/core";
import { DictationClient } from "@suki-sdk/dictation";
import { DictationProvider, Dictation } from "@suki-sdk/dictation-react";

export function NotesWithDictation() {
  const client = useMemo(() => {
    const authManager = new SukiAuthManager({
      partnerId: "YOUR_PARTNER_ID", // replace with your partner ID - required
      partnerToken: "YOUR_PARTNER_TOKEN", // replace with your partner token - required
      environment: "staging", // optional: "staging" | "production"
      loginOnInitialize: true, // optional: sign in as soon as this runs
      autoRegister: false, // optional: enable provider auto-registration
      providerId: "YOUR_PROVIDER_ID", // optional: provider identifier in your system
      providerName: "YOUR_PROVIDER_NAME", // optional: full provider display name
      providerOrgId: "YOUR_PROVIDER_ORG_ID", // optional: organization identifier for the provider in your system
      providerSpecialty: "YOUR_PROVIDER_SPECIALTY", // optional: clinical specialty
    });
    return new DictationClient({ authManager });
  }, []);

  const [notes, setNotes] = useState("");
  const [dictationActive, setDictationActive] = useState(false);

  return (
    <DictationProvider client={client}>
      <textarea
        id="clinical-notes"
        value={notes}
        onChange={(e) => setNotes(e.target.value)}
      />
      <button
        type="button"
        onClick={() => setDictationActive((v) => !v)}
      >
        {dictationActive ? "Stop dictation" : "Start dictation"}
      </button>
      {dictationActive && (
        <Dictation
          fieldId="clinical-notes"
          mode="in-field"
          initialText={notes}
          onSubmit={({ text }) => setNotes(text)}
          onCancel={() => setDictationActive(false)}
        />
      )}
    </DictationProvider>
  );
}
```

Your integration is working when turning Dictation on shows the hosted UI, committed text updates **`notes`** through **`onSubmit`**, and **only one** **`<Dictation>`** is mounted at a time for that **`client`**.

## Best practices

<Tip>
  * **Reuse one Dictation client.** Build a single **DictationClient** inside **`useMemo`** (or equivalent) for the page or shell. Creating a new client on every render breaks that pattern and often resets the hosted UI.

  * **Reuse one auth manager.** Create **SukiAuthManager** once inside the same **`useMemo`** as the client, as in the steps above.

  * **Handle when the user commits.** You must pass **`onSubmit`** so the SDK can deliver the final text. Without it, Dictation often closes right after the user tries to finish.

  * **Pick a clear field label.** Each session needs a stable, unique **fieldId** in callbacks. Using the same value as the target input's **id** is a simple way to know which element to update. Refer to [Field IDs](/dictation-sdk/guides/configuration#field-ids-in-practice) guide for more details.

  * **Give the Dictation host real height.** The node you use for **`rootElement`** (when you set it) should have height you control. Otherwise the Dictation area can look blank. Refer to [Error handling](/dictation-sdk/guides/error-handling) and [In-field mode](/dictation-sdk/guides/in-field-mode) guides for more details.

  * **One active Dictation at a time.** Use boolean state or **`activeFieldId`** so you do not mount multiple Dictation UIs against the same **`client`** at once.

  * **Rely on unmount for hide.** Removing **`<Dictation>`** is the normal way to tear down the UI; you usually do not call **`hide()`** yourself in React.
</Tip>

## Available cookbooks

<div className="hp-io-method-grid tut-hub-card-grid" data-cookbook-related-grid>
  <a className="hp-io-method-card tut-hub-method-card" href="/documentation/cookbooks/dictation-onsubmit-chart-field">
    <div className="tut-hub-card-media" aria-hidden="true" />

    <div className="hp-io-method-card-body">
      <div className="tut-hub-card-badges">
        <span className="hp-wn-badge hp-wn-badge-new">Dictation</span>
        <span className="hp-wn-badge cookbook-hub-badge-surface cookbook-hub-badge-surface--sdk">SDK</span>
      </div>

      <h3 className="hp-io-method-card-title">Write Dictation Text to an EHR Field</h3>

      <p className="hp-io-method-card-desc cookbook-hub-card-desc">
        Write Dictation text with onSubmit.
      </p>

      <div className="hp-io-method-card-meta tut-hub-card-foot" aria-label="5 min">
        <div className="tut-hub-card-foot-meta">
          <span className="hp-io-method-card-meta-time">5 min</span>
        </div>
      </div>
    </div>
  </a>
</div>

## Available tutorials

<div className="hp-io-method-grid tut-hub-card-grid">
  <a className="hp-io-method-card tut-hub-method-card" href="/documentation/tutorials/dictation-sdk-chart-field">
    <div className="tut-hub-card-media" aria-hidden="true" />

    <div className="hp-io-method-card-body">
      <span className="hp-wn-badge hp-wn-badge-new">Dictation SDK</span>
      <h3 className="hp-io-method-card-title">Build Dictation into a Chart Field</h3>

      <p className="hp-io-method-card-desc">
        Mount Dictation in-field mode on a chart textarea with one shared DictationClient in React.
      </p>

      <div className="hp-io-method-card-meta tut-hub-card-foot" aria-label="15 min, Intermediate">
        <div className="tut-hub-card-foot-meta">
          <span className="hp-io-method-card-meta-time">15 min</span>
          <span className="tut-hub-level">Intermediate</span>
        </div>
      </div>
    </div>
  </a>
</div>

## Next steps

Refer to the following guides for more information.

<Icon icon="file-lines" iconType="solid" /> [Configuration](/dictation-sdk/guides/configuration) to learn about the available options and how to use them.
<Icon icon="file-lines" iconType="solid" /> [Javascript integration](/dictation-sdk/javaScript-integration/javaScript) to learn how to integrate the Dictation SDK with plain JavaScript.
