Experience (React)

React component for embedding Avatar Experiences with ref-based control.

Overview

Experience from @liforma/client/react mirrors the Svelte component: session creation, player attachment, event delivery, restart on launch-option changes, and cleanup on unmount. The entry is marked 'use client' for Next.js App Router.

Basic usage

Import the component in a client boundary and pass experienceId (or manifest / sessionEndpoint for server-session flows).

Demo.tsx
import { Experience } from '@liforma/client/react';

export function Demo() {
  return <Experience experienceId="exp_01DEMO1SPANISHCAFE" />;
}

Host-controlled speech and listening

Use a ref typed as ExperienceHandle to call speak(), startListening(), and related methods from your own UI. Wait for onStarted (or await ref.current.started()) before speech methods — the player start button unlocks audio.

Lesson.tsx
import { useRef, useState } from 'react';
import {
  Experience,
  type ExperienceHandle
} from '@liforma/client/react';

export function Lesson() {
  const experienceRef = useRef<ExperienceHandle>(null);
  const [audioUnlocked, setAudioUnlocked] = useState(false);

  async function handleStarted() {
    setAudioUnlocked(true);
    await experienceRef.current?.speak({ text: 'Welcome to the lesson.' });
  }

  return (
    <>
      <Experience
        ref={experienceRef}
        experienceId="exp_01DEMO1SPANISHCAFE"
        mode="presenter"
        speechInputMode="manual"
        onStarted={handleStarted}
      />
      <button
        disabled={!audioUnlocked}
        onClick={() => experienceRef.current?.startListening()}
      >
        Start answer
      </button>
      <button
        disabled={!audioUnlocked}
        onClick={() => experienceRef.current?.stopListening()}
      >
        Stop answer
      </button>
    </>
  );
}

ExperienceProps

Props match Experience (Svelte) ExperienceProps — same names and semantics, including speechOnly.

Callback props

Pass React event props such as onReady, onStarted, and onUserTranscript. Updating a callback does not restart the session; the component always invokes the latest handler.

conversationProcessor is an exception: changing its function reference restarts the session. Wrap it in useCallback when the implementation is stable.

Strict Mode

Under React Strict Mode the component mounts twice in development. Session generations are gated so stale async work from the first mount does not surface errors after unmount.

Example

See the guided-practice React (Vite) example for a full presenter + manual listening lesson loop.