Events
BambuserVideoView surfaces the player's lifecycle and runtime events through callback props. All callbacks receive a synthetic event with the payload under e.nativeEvent.
onStatus
Playback state changed.
{ id: string; state: BambuserPlayerState }
state is one of:
'ready' · 'loading' · 'playing' · 'paused' · 'stopped' · 'completed' · 'error' · 'idle' · 'buffering'
onProgress
Periodic progress updates.
{ id: string; duration: number; currentTime: number }
Both values are in seconds.
onError
An unrecoverable error occurred (for example, an invalid or unpublished show ID, or a network failure during initialisation).
{ id: string; message: string }
When the player enters an error state, onStatus also fires with state: 'error'.
onEvent
Custom events emitted by the player (add-to-cart, wishlist, share, action-card-clicked, etc.).
{ id: string; type: string; data: any }
The data shape depends on the event type. See the Bambuser Player API Reference for the full event catalog.
Platform differences
The native iOS and Android SDKs surface event payloads slightly differently. Read both locations to stay portable:
callbackKey: on iOS the callback key lives atdata.callbackKey; on Android it is at the top level (e.nativeEvent.callbackKey):const callbackKey = e.nativeEvent.callbackKey ?? e.nativeEvent.data?.callbackKey;
Event data shape: some event payloads nest data under
data.eventon iOS and at the top level on Android. For example, anadd-to-wishlistSKU is atdata.event.sku(iOS) ordata.sku(Android):const sku = Platform.OS === 'ios'
? e.nativeEvent.data?.event?.sku
: e.nativeEvent.data?.sku;
Example: respond to should-add-item-to-cart
function onEvent(e) {
const { type, data } = e.nativeEvent;
const callbackKey = e.nativeEvent.callbackKey ?? data?.callbackKey;
if (type === 'should-add-item-to-cart' && callbackKey) {
const sku = Platform.OS === 'ios' ? data?.event?.sku : data?.sku;
addToCart(sku).then((success) => {
playerRef.current?.notify(callbackKey, {
success,
reason: success ? undefined : 'out-of-stock',
});
});
}
}
See Player API › notify for the response contract.
onPiPStateChanged
Picture-in-Picture state changed.
{ id: string; state: BambuserPiPState }
state is one of:
| State | Fires when | Platform |
|---|---|---|
'willStart' | Right before PiP begins. | Both |
'started' | PiP is active. | Both |
'willStop' | Right before PiP ends (programmatic stop). | Both |
'stopped' | PiP has ended. | Both |
'restored' | User tapped "Go to full screen" from the PiP window. | iOS only |
onThumbnailTapped (iOS)
User tapped the video thumbnail before playback started.
{ id: string }
Full example
import { useRef } from 'react';
import { Platform, StyleSheet } from 'react-native';
import {
BambuserVideoView,
type BambuserVideoViewRef,
} from '@bambuser/react-native-commerce-sdk';
export function LivePlayerScreen() {
const playerRef = useRef<BambuserVideoViewRef>(null);
const handleEvent = (e) => {
const { type, data } = e.nativeEvent;
const callbackKey = e.nativeEvent.callbackKey ?? data?.callbackKey;
if (type === 'provide-product-data') {
const products = Platform.OS === 'ios'
? data?.event?.products
: data?.products;
products?.forEach((product) => {
const hydrationJson = buildProductJson(product.ref);
playerRef.current?.invoke(
'updateProductWithData',
`'${product.id}', ${hydrationJson}`,
);
});
}
if (type === 'should-add-item-to-cart' && callbackKey) {
const sku = Platform.OS === 'ios' ? data?.event?.sku : data?.sku;
addToCart(sku).then((success) =>
playerRef.current?.notify(callbackKey, { success }),
);
}
};
return (
<BambuserVideoView
ref={playerRef}
style={StyleSheet.absoluteFill}
id="your-show-id"
configuration={{ autoplay: true, currency: 'USD', locale: 'en-US' }}
onEvent={handleEvent}
onStatus={(e) => console.log('state:', e.nativeEvent.state)}
onError={(e) => console.error('player error:', e.nativeEvent.message)}
/>
);
}