Skip to main content

React Host

This page covers embedding Myop components in a host React app using @myop/react. If you want to author a Myop component, see the CLI guide instead.

Looking for the API reference? @myop/react reference ยท Single-file SDK reference

Installationโ€‹

npm install @myop/react @myop/sdk

@myop/sdk is a peer dependency. Requires React 18+.

Minimal exampleโ€‹

import { MyopComponent } from "@myop/react";

export function App() {
return (
<MyopComponent
componentId="your-component-id"
data={{ title: "Hello", items: ["a", "b"] }}
onItemSelected={(payload) => console.log(payload)}
style={{ width: 400, height: 300 }}
/>
);
}

That's the whole contract. componentId is a UUID from the Myop dashboard. Everything else is optional.

CTA actions emitted by the component show up as on<PascalCase> props on the host โ€” see Receiving events below.

Never create iframes manually

Always use <MyopComponent>. Never hand-roll an <iframe> pointing at a Myop component โ€” the SDK handles iframe lifecycle, messaging, sizing, caching, and error recovery for you.

Passing data inโ€‹

The data prop is delivered to the component's myop_init_interface. It's reactive โ€” updates trigger a re-init inside the iframe:

const [count, setCount] = useState(0);

<MyopComponent
componentId="counter"
data={{ count }}
/>

data can be any JSON-serializable value. Functions are not transferred.

Receiving events (CTA handlers)โ€‹

Components emit CTA events via myop_cta_handler(action, payload). The host receives them through typed per-action props โ€” kebab-case actions become onPascalCase props. This is the canonical form; use it in new code.

<MyopComponent
componentId="task-list"
data={{ tasks }}
onTaskToggled={({ taskId, completed }) => {
setTasks((prev) =>
prev.map((t) => (t.id === taskId ? { ...t, completed } : t))
);
}}
onTaskDeleted={({ taskId }) => {
setTasks((prev) => prev.filter((t) => t.id !== taskId));
}}
/>
Component CTA actionReact prop
item-selectedonItemSelected
form-submittedonFormSubmitted
task-toggledonTaskToggled

Fallback: generic handlerโ€‹

For dynamically named actions or quick experiments, a generic on prop receives every event. Use this only when the typed form doesn't fit:

<MyopComponent
componentId="task-list"
data={{ tasks }}
on={(action, payload) => {
if (action === "task-toggled") setTasks(/* ... */);
}}
/>

Don't mix on with on<Action> props for the same action โ€” pick one per component instance.

Propsโ€‹

PropTypeDescription
componentIdstringMyop component UUID
dataTDataPassed to myop_init_interface; reactive
on(action, payload) => voidGeneric CTA handler
on[ActionName](payload) => voidTyped handler for one CTA
onLoad(component) => voidFired after load completes
onError(error: string) => voidFired on load failure
styleCSSPropertiesContainer styles
loaderReactNodeCustom loading indicator
fallbackReactNodeCustom error fallback
autoSizebooleanAuto-size container to content
environmentstringLoad from a specific environment
previewbooleanLoad unpublished preview version

Auto-generated typed packagesโ€‹

Every Myop component has an auto-generated npm package that bakes in the componentId and exposes a fully-typed component:

npm install https://cloud.myop.dev/npm/{componentId}/react
import { TaskList } from "@myop/task-list";

<TaskList
data={{ tasks }}
onTaskToggled={(payload) => {
// payload is typed: { taskId: string; completed: boolean }
}}
/>

Recommended for production. Types come from the component's <script type="myop/types"> block.

Preloadingโ€‹

Eagerly fetch components to avoid loading delay on first render:

import { preloadComponents, isPreloaded } from "@myop/react";

await preloadComponents(["id-1", "id-2"]);

Local devโ€‹

Point the SDK at a local component dev server (port 9292 by default):

import { enableLocalDev } from "@myop/react";

if (import.meta.env.DEV) enableLocalDev();

You can also enable via a URL param without code changes โ€” open the app with ?env=dev.

Run a component locally with:

cd path/to/your-component
npx myop dev

The dev server registers the component with the local repository and hot-reloads on file changes.

Configurationโ€‹

All SDKs export the same configuration functions:

import {
enableLocalDev,
setCloudRepositoryUrl,
setEnvironment,
} from "@myop/react";

enableLocalDev(); // Load from localhost:9292
setCloudRepositoryUrl("https://custom"); // Custom cloud URL
setEnvironment("staging"); // Default environment

Where to nextโ€‹