@myop/react-native
Official React Native bindings for embedding Myop components in your React Native applications.
Myop components are framework-agnostic UI components that can be updated in real-time without redeploying your application. Build once, embed anywhere, and iterate instantly. Perfect for teams that need to ship UI changes fast, A/B test components, or empower non-developers to customize the interface. Myop is also the safest way to adopt AI-generated components in your application—whether created by developers or non-developers—with built-in sandboxing and controlled integration.
Website | Documentation | Dashboard | Discord
Installation
npm install @myop/react-native
Install the required peer dependency:
npm install react-native-webview
Auto-Generated React Native Components
Myop automatically generates a typed React Native component package for every component you create in the dashboard. Install it directly via npm:
npm install https://cloud.myop.dev/npm/{component-id}/react-native
Then import and use it like any React Native component. For example, if you created a table component called "users-table" in the dashboard:
import { UsersTable } from "@myop/users-table";
export default function App() {
const users = [
{ id: 1, name: "Alice", email: "alice@example.com", role: "Admin" },
{ id: 2, name: "Bob", email: "bob@example.com", role: "User" },
{ id: 3, name: "Charlie", email: "charlie@example.com", role: "User" },
];
return (
<UsersTable
data={{ rows: users }}
onRowClicked={(payload) => {
console.log("Selected user:", payload.rowData);
}}
onDeleteClicked={(payload) => {
deleteUser(payload.userId);
}}
onExportRequested={(payload) => {
exportToFormat(payload.format); // "csv" | "xlsx"
}}
style={{ flex: 1 }}
/>
);
}
Why this is powerful:
- Fully typed — The generated package includes complete TypeScript types for your component's data interface and all CTA event payloads
- Auto loaded — Components are fetched and rendered automatically, no manual setup required
- Not in your code — The actual component implementation lives on Myop and is loaded at runtime. Update your component in the dashboard and it's instantly live—no rebuild, no redeploy
- Zero bundle impact — Auto-generated component packages are just thin typed wrappers. The actual component implementations are loaded at runtime via WebView, meaning your Myop components can be as complex, feature-rich, and heavy as you need without adding to your application bundle
Environment options:
Set the default environment for all components using setEnvironment:
import { setEnvironment } from "@myop/react-native";
// Set default environment for all component loads
setEnvironment("staging");
You can also override the environment directly on a specific component:
<UsersTable
data={{ rows: users }}
preview={true} // Load unpublished preview version
environment="staging" // Load from specific environment (prod, staging, etc.)
style={{ flex: 1 }}
/>
Environments are fully configurable in the dashboard, allowing you to test changes in staging before publishing to production.
For more details on auto-generated packages, see the Auto-Generated Packages documentation.
Requirements
| Dependency | Version |
|---|---|
| React | >= 16.8.0 |
| React Native | >= 0.60.0 |
| react-native-webview | >= 11.0.0 |
Quick Start
import { MyopComponent } from '@myop/react-native';
export default function App() {
return (
<MyopComponent
componentId="your-component-id"
style={{ flex: 1 }}
/>
);
}
Usage
Loading by Component ID
The simplest way to embed a Myop component:
<MyopComponent
componentId="abc123"
style={{ flex: 1 }}
/>
Passing Data to Components
Use the data prop to send data to your component's myop_init_interface:
const [userData, setUserData] = useState({ name: 'John', theme: 'dark' });
<MyopComponent
componentId="abc123"
data={userData}
style={{ flex: 1 }}
/>
When data changes, myop_init_interface is automatically called with the new value.
Handling Component Events
Listen for events from your component's myop_cta_handler:
<MyopComponent
componentId="abc123"
on={(action, payload) => {
switch (action) {
case 'submit':
handleSubmit(payload);
break;
case 'navigate':
navigation.navigate(payload.screen);
break;
}
}}
style={{ flex: 1 }}
/>
Component Proxy API
Access the component instance for direct manipulation:
import { IMyopComponentProxy } from '@myop/react-native';
const [component, setComponent] = useState<IMyopComponentProxy | null>(null);
<MyopComponent
componentId="abc123"
onLoad={(proxy) => setComponent(proxy)}
style={{ flex: 1 }}
/>
// Send data to component
component?.props.myop_init_interface({ theme: 'dark' });
// DOM manipulation
component?.element.style.set('opacity', '0.5');
component?.element.set('style.background', 'red');
// Get values (async)
const opacity = await component?.element.style.get('opacity');
const scrollTop = await component?.element.get('scrollTop');
// Lifecycle methods
component?.hide();
component?.show();
component?.dispose();
Loading & Error States
By default, no loader is shown while the component loads. The Myop-branded fallback is displayed automatically on error.
Using the Default Myop Loader
import { MyopComponent, MyopLoader } from '@myop/react-native';
<MyopComponent
componentId="abc123"
loader={<MyopLoader />} // Opt-in to default Myop loader
fadeDuration={300}
style={{ flex: 1 }}
/>
Custom Loading State
Provide your own loading component:
import { ActivityIndicator, View } from 'react-native';
<MyopComponent
componentId="abc123"
loader={
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<ActivityIndicator size="large" color="#0000ff" />
</View>
}
fadeDuration={300}
style={{ flex: 1 }}
/>
Custom Error Fallback
Display a custom view when the component fails to load:
import { MyopComponent, MyopFallback } from '@myop/react-native';
<MyopComponent
componentId="abc123"
fallback={
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Unable to load component</Text>
</View>
}
onError={(error) => console.error('Load failed:', error)}
style={{ flex: 1 }}
/>
// Or use the default Myop fallback explicitly
<MyopComponent
componentId="abc123"
fallback={<MyopFallback />}
style={{ flex: 1 }}
/>
Using Component Configuration
For advanced use cases, pass a full configuration object:
import { MyopComponent, IComponentInstanceConfig } from '@myop/react-native';
const config: IComponentInstanceConfig = {
id: 'instance-1',
componentId: 'abc123',
componentName: 'MyComponent',
skinSelector: {
type: 'Dedicated',
skin: { id: 'skin-1' }
}
};
<MyopComponent
componentConfig={config}
style={{ flex: 1 }}
/>
Environment Selection
Target different deployment environments:
<MyopComponent
componentId="abc123"
environment="staging" // defaults to "production"
style={{ flex: 1 }}
/>
WebView Behavior
Control scroll, zoom, and text selection:
<MyopComponent
componentId="abc123"
scrollEnabled={true} // Enable scrolling (default: false)
zoomEnabled={true} // Enable pinch-to-zoom (default: false)
selectionEnabled={true} // Enable text selection (default: false)
style={{ flex: 1 }}
/>
Preloading Components
Preload components for instant rendering when they're displayed:
import { preloadComponents, isPreloaded } from '@myop/react-native';
// Preload on app startup or before navigating
await preloadComponents(['component-1', 'component-2']);
// Check if component is preloaded
if (isPreloaded('component-1')) {
// Component will render instantly without loader
}
Configuration APIs
Configure the CloudRepository for custom endpoints or local development:
import {
enableLocalDev,
setCloudRepositoryUrl,
setCloudRepository,
setEnvironment,
getCloudRepository
} from '@myop/react-native';
// Enable local development mode (connects to localhost:9292)
enableLocalDev();
// Use a custom endpoint
setCloudRepositoryUrl('https://custom.myop.dev');
// Set default environment for all components
setEnvironment('staging');
// Get the current CloudRepository instance
const repo = getCloudRepository();
API Reference
MyopComponent Props
| Prop | Type | Default | Description |
|---|---|---|---|
componentId | string | - | Component ID to load from Myop cloud |
componentConfig | IComponentInstanceConfig | - | Full component configuration object |
data | any | - | Data passed to myop_init_interface |
on | (action: string, payload?: any) => void | - | Handler for myop_cta_handler events |
onLoad | (proxy: IMyopComponentProxy) => void | - | Callback with component proxy when loaded |
onError | (error: string) => void | - | Callback when component fails to load |
loader | ReactNode | null | Loading component (default: no loader). Use <MyopLoader /> for default Myop loader |
fallback | ReactNode | <MyopFallback /> | Error fallback component (default: Myop-branded fallback) |
fadeDuration | number | 200 | Loader fade-out duration in ms |
environment | string | "production" | Target environment |
preview | boolean | false | Load preview version of component |
scrollEnabled | boolean | false | Enable WebView scrolling |
zoomEnabled | boolean | false | Enable pinch-to-zoom |
selectionEnabled | boolean | false | Enable text selection |
style | StyleProp<ViewStyle> | - | Container styles |
Either componentId or componentConfig must be provided.
Exported Components
| Component | Description |
|---|---|
MyopComponent | Main component for embedding Myop content |
MyopLoader | Default animated loading state |
MyopFallback | Default error/fallback state |
Exported Functions
| Function | Description |
|---|---|
preloadComponents(ids, env?, preview?) | Preload components for instant rendering |
isPreloaded(componentId, env?, preview?) | Check if a component is cached |
enableLocalDev() | Enable local development mode (localhost:9292) |
setCloudRepositoryUrl(url) | Set a custom CloudRepository URL |
setCloudRepository(repository) | Set a custom CloudRepository instance |
setEnvironment(env) | Set the default environment |
getCloudRepository() | Get the current CloudRepository instance |
Types
interface IMyopComponentProxy {
id: string;
props: {
myop_init_interface: (data: any) => void;
myop_cta_handler: ((action: string, payload?: any) => void) | null;
};
element: IElementProxy;
dispose: () => void;
hide: () => void;
show: () => void;
inspect: () => void;
}
interface IElementProxy {
set: (path: string, value: any) => void;
get: (path: string) => Promise<any>;
style: {
set: (property: string, value: string) => void;
get: (property: string) => Promise<string>;
};
}
interface IComponentInstanceConfig {
id: string;
componentId: string;
componentName: string;
skinSelector: ISkinSelectorConfig;
nestedComponents?: IComponentInstanceConfig[];
resolvedExperiences?: IExperience[];
resolvedNestedComponents?: IComponentConfig[];
[key: string]: any;
}
interface MyopLoaderRef {
fadeOut: (duration?: number) => void;
}
License
MIT