CoHostState core module for managing host co-hosting sessions. This guide walks you through combining these tools to implement a complete co-hosting workflow for live streaming scenarios.
CoHostState module to enable this functionality.requestHostConnection method.import { useCoHostState } from 'react-native-tuikit-atomic-x/lib/module/atomic-x/state/CoHostState';const liveID = 'xxx'; // Host A's room ID// Retrieve CoHostState instance by liveIDconst { requestHostConnection } = useCoHostState(liveID);// User clicks the "Co-host" button and selects Host Bconst handleRequestHostConnection = (targetHostLiveID) => {requestHostConnection({liveID, // Host A's room IDtargetHostLiveID, // Host B's room IDlayoutTemplate: 'HOST_DYNAMIC_GRID', // Select layout templatetimeout: 30, // Invitation timeoutonSuccess: () => { console.log('Co-host invitation sent, waiting for response...'); },onError: (error) => { console.log('Invitation failed to send', error); },});};
addCoHostListener to subscribe to events and handle Host B's response.import { useEffect } from 'react';import { useCoHostState } from 'react-native-tuikit-atomic-x/lib/module/atomic-x/state/CoHostState';const liveID = 'xxx'; // Host A's room ID// Retrieve CoHostState instance by liveIDconst { addCoHostListener, removeCoHostListener } = useCoHostState(liveID);useEffect(() => {const onCoHostRequestAccepted = (event) => {console.log('Host accepted your co-host invitation', event);};const onCoHostRequestRejected = (event) => {console.log('Host rejected your co-host invitation', event);};const onCoHostRequestTimeout = () => {console.log('Invitation timed out, no response from the other party');};addCoHostListener('onCoHostRequestAccepted', onCoHostRequestAccepted);addCoHostListener('onCoHostRequestRejected', onCoHostRequestRejected);addCoHostListener('onCoHostRequestTimeout', onCoHostRequestTimeout);return () => {removeCoHostListener('onCoHostRequestAccepted', onCoHostRequestAccepted);removeCoHostListener('onCoHostRequestRejected', onCoHostRequestRejected);removeCoHostListener('onCoHostRequestTimeout', onCoHostRequestTimeout);};}, []);
onCoHostRequestReceived event with addCoHostListener so Host B can listen for invitations from Host A.import { useEffect } from 'react';import { useCoHostState } from 'react-native-tuikit-atomic-x/lib/module/atomic-x/state/CoHostState';const liveID = 'xxx'; // Host B's room ID// Retrieve CoHostState instance by liveIDconst { addCoHostListener, removeCoHostListener } = useCoHostState(liveID);useEffect(() => {const onCoHostRequestReceived = (event) => {const inviterData = JSON.parse(event.inviter);console.log('Received co-host invitation', inviterData);// You can trigger a popup prompt here};addCoHostListener('onCoHostRequestReceived', onCoHostRequestReceived);return () => {removeCoHostListener('onCoHostRequestReceived', onCoHostRequestReceived);};}, []);
import { useCoHostState } from 'react-native-tuikit-atomic-x/lib/module/atomic-x/state/CoHostState';const liveID = 'xxx'; // Host B's room ID// Retrieve CoHostState instance by liveIDconst { acceptHostConnection, rejectHostConnection } = useCoHostState(liveID);// Host B accepts the co-host invitationconst handleAcceptHostConnection = (fromHostLiveID) => {acceptHostConnection({liveID,fromHostLiveID, // Obtain this data from the onCoHostRequestReceived eventonSuccess: () => { console.log('Co-host invitation accepted'); },onError: (error) => { console.log('Failed to accept co-host invitation', error); },});};// Host B rejects the co-host invitationconst handleRejectHostConnection = (fromHostLiveID) => {rejectHostConnection({liveID,fromHostLiveID, // Obtain this data from the onCoHostRequestReceived eventonSuccess: () => { console.log('Co-host invitation rejected'); },onError: (error) => { console.log('Failed to reject co-host invitation', error); },});};


import React, { useMemo } from 'react';import { View, Text, Image, StyleSheet, Dimensions } from 'react-native';const DEFAULT_AVATAR = 'https://liteav-test-1252463788.cos.ap-guangzhou.myqcloud.com/voice_room/voice_room_cover1.png';const { width: SCREEN_WIDTH } = Dimensions.get('window');// Receives core data from parent: seatList and canvasexport default function ParticipantOverlay({ seatList, canvas }) {if (!seatList || seatList.length === 0) return null;// Calculate scaling ratio based on canvasconst scale = useMemo(() => {if (!canvas?.w || !canvas?.h) return { scaleX: 1, scaleY: 1 };const displayWidth = SCREEN_WIDTH;const displayHeight = SCREEN_WIDTH * (canvas.h / canvas.w);return {scaleX: displayWidth / canvas.w,scaleY: displayHeight / canvas.h,};}, [canvas]);// Compute the position and size of each participant's UI containerconst getParticipantStyle = (participant) => {if (!participant?.region) return {};return {position: 'absolute',left: participant.region.x * scale.scaleX,top: participant.region.y * scale.scaleY,width: participant.region.w * scale.scaleX,height: participant.region.h * scale.scaleY,};};return (// overlay-container<View style={styles.overlayContainer} pointerEvents="none">{/* Iterate seatList, create a separate UI container for each participant */}{seatList.map((participant) => {if (!participant?.userInfo?.userID) return null;const isCameraOff = participant.userInfo.cameraStatus === 'OFF';return (// participant-ui-container<View key={participant.userInfo.userID} style={getParticipantStyle(participant)}>{/* Conditional rendering: show different UI based on camera status */}{isCameraOff ? (// 1. When camera is off, show centered avatar and nickname<View style={styles.avatarPlaceholder}><Imagestyle={styles.avatarImage}source={{ uri: participant.userInfo.userAvatar || DEFAULT_AVATAR }}/><Text style={styles.avatarName}>{participant.userInfo.userName || participant.userInfo.userID}</Text></View>) : (// 2. When camera is on, show nickname bar at bottom left<View style={styles.nicknameBar}><Text style={styles.nicknameText}>{participant.userInfo.userName || participant.userInfo.userID}</Text></View>)}</View>);})}</View>);}const styles = StyleSheet.create({overlayContainer: {position: 'absolute',top: 0,left: 0,right: 0,bottom: 0,},avatarPlaceholder: {flex: 1,backgroundColor: '#2E323A',justifyContent: 'center',alignItems: 'center',},avatarImage: {width: 60,height: 60,borderRadius: 30,},avatarName: {marginTop: 8,fontSize: 13,color: '#fff',},nicknameBar: {position: 'absolute',left: 6,bottom: 6,backgroundColor: 'rgba(0, 0, 0, 0.5)',paddingHorizontal: 8,paddingVertical: 3,borderRadius: 10,},nicknameText: {color: '#fff',fontSize: 11,},});
import React from 'react';import { StyleSheet, View } from 'react-native';import { LiveCoreView } from 'react-native-tuikit-atomic-x/lib/module/components/LiveCoreView';import { useLiveSeatState } from 'react-native-tuikit-atomic-x/lib/module/atomic-x/state/LiveSeatState';import ParticipantOverlay from '../../components/ParticipantOverlay';export default function YourAnchorScreen({ route, navigation }) {const { liveID } = route.params || {};const { seatList, canvas } = useLiveSeatState(liveID);return (// page-container<View style={styles.pageContainer}>{/* live-container */}<View style={styles.liveContainer}>{/* Bottom layer: video rendering layer */}<LiveCoreViewliveID={liveID}coreViewType="pushView" // Host side: pushView, Audience side: playViewstyle={styles.videoLayer}/>{/* Top layer: custom UI overlay */}<ParticipantOverlay seatList={seatList} canvas={canvas} /></View>{/* Other UI elements on the page, such as the bottom control bar */}{/* <View style={styles.bottomControls}>...</View> */}</View>);}const styles = StyleSheet.create({pageContainer: {flex: 1,backgroundColor: '#000',},liveContainer: {flex: 1,},videoLayer: {flex: 1,},});
State | Function Description | API Documentation |
DeviceState | Audio/Video device control: microphone (on/off, volume), camera (on/off, switch, quality), screen sharing, real-time device status monitoring. | |
CoHostState | Host co-hosting: supports multiple layout templates (dynamic grid, etc.), initiate/accept/reject co-hosting, co-host interaction management. |
targetHostLiveID is correct and that the recipient's live room is actively streaming.Was this page helpful?
You can also Contact sales or Submit a Ticket for help.
Help us improve! Rate your documentation experience in 5 mins.
Feedback