> Lettrove docs 1.x · https://docs.lettrove.com/docs/api/react

# `@lettrove/react`

```bash
npm install @lettrove/react
```

React 18 or newer. Built on [`@lettrove/embed`](/docs/api/embed), which it installs.

```tsx
import { useRef } from 'react';
import { LettroveEditor, type EditorHandle } from '@lettrove/react';

export function Designer({ designId }: { designId?: string }) {
  const editor = useRef<EditorHandle | null>(null);
  return (
    <>
      <button onClick={async () => console.log((await editor.current?.exportHtml())?.html)}>Export</button>
      <LettroveEditor
        ref={editor}
        publishableKey="lt_pk_test_…"
        getToken={getToken}
        designId={designId}
        appearance={{ variables: { accent: '#5b3df5' } }}
        onDesignSaved={({ designId }) => save(designId)}
        onError={(e) => console.error(e.code, e.message)}
        style={{ height: 720 }}
      />
    </>
  );
}
```

## Props

Every option of [`createEditor`](/docs/api/embed#options) except `container`, `signal` and `on`
(the component provides those): `publishableKey`, `getToken`, `designId`, `release`, `mode`, `tabs`,
`tools`, `features`, `branding`, `appearance`. Plus:

| Prop | |
|---|---|
| `className`, `style` | For the element the editor fills. Give it a height. |
| `onReady(editor)` | The editor is on screen; `editor` is the [`EditorHandle`](/docs/api/embed#editorhandle). |
| `onError(error)` | It could not open, or reported an error while open. `error.code`, `error.message`. |
| `onDesignLoaded` | `design:loaded` |
| `onDesignUpdated` | `design:updated` |
| `onDesignSaved` | `design:saved` |
| `onSelectionChanged` | `selection:changed` |
| `onImageUploaded` | `image:uploaded` |
| `onConfigAdjusted` | `config:adjusted` |
| `onThemeChanged` | `theme:changed` |

Payloads: [Events](/docs/editor/events).

## `ref`

The [`EditorHandle`](/docs/api/embed#editorhandle) once the editor is open, `null` before and after.

## Behaviour you can rely on

- **StrictMode**: mounting twice in development leaves one editor.
- **Server rendering** (Next.js, Remix): renders an empty element; the editor opens in the browser.
  In the Next.js App Router it is already a client component; render it from a `'use client'` file
  of your own, since `getToken` is a function ([Next.js](/docs/get-started/nextjs)).
- **Changing props**: inline functions and objects may change on every render without reopening the
  editor. A new `publishableKey`, `designId`, `release` or set of options opens it again; a new
  `appearance.theme` switches the open editor without reopening.
- **Unmounting** removes the editor and everything it set up.

## Exports

`LettroveEditor`, `LettroveEditorProps`, and the types of `@lettrove/embed` (`EditorHandle`,
`ExportResult`, `LettroveEmbedError`…).
