Invite Guest on Stage - React Native
This guide explains the process of inviting a viewer to join a livestream using the changeMode()
method.
Before proceeding with this guide, ensure that all attendees join the meeting with the mode set to SIGNALLING_ONLY
, while the host joins with the mode set to SEND_AND_RECV
.
Important Changes React Native SDK in Version v0.2.0
- The following modes have been deprecated:
CONFERENCE
has been replaced bySEND_AND_RECV
VIEWER
has been replaced bySIGNALLING_ONLY
Please update your implementation to use the new modes.
⚠️ Compatibility Notice:
To ensure a seamless meeting experience, all participants must use the same SDK version.
Do not mix version v0.2.0 + with older versions, as it may cause significant conflicts.
The diagram below illustrates the utilization of the PubSub
mechanism to facilitate the requesting and switching of the participant's mode.
Step 1: Loading the Viewer List
First, the host will be presented with a list of participants who have joined as SIGNALLING_ONLY
, accompanied by a button that, when selected, will invite that user to join the livestream.
import { useMeeting, useParticipant } from "@videosdk.live/react-native-sdk";
import { SafeAreaView, TouchableOpacity, Text, View } from "react-native";
function MeetingView() {
return (
<>
<Text>Viewer List</Text>
<ViewerList />
</>
);
}
function ViewerList() {
const { participants } = useMeeting();
//Filtering only viewer participant
const viewers = [...participants.values()].filter((participant) => {
return participant.mode == Constants.modes.SIGNALLING_ONLY;
});
return (
<SafeAreaView style={{ flex: 1 }}>
{viewers.map((participant) => {
return <ViewerListItem participantId={participant.id} />;
})}
</SafeAreaView>
);
}
function ViewerListItem({ participantId }) {
const { displayName } = useParticipant(participantId);
return (
<View
style={{
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
marginVertical: 8,
}}
>
<Text>{displayName}</Text>
<TouchableOpacity
style={{
marginLeft: 12,
borderWidth: 1,
borderRadius: 12,
padding: 12,
}}
>
<Text>Request to join Livestream</Text>
</TouchableOpacity>
</View>
);
}

Step 2: Requesting a Viewer to Join Livestream
Now, with the Viewer list in place, handle the click event for the "Join Livestream" button by utilizing CHANGE_MODE_$participantId
as the topic for PubSub.
import { usePubSub } from "@videosdk.live/react-native-sdk";
function ViewerListItem({ participantId }) {
const { displayName } = useParticipant(participantId);
const { publish } = usePubSub(`CHANGE_MODE_${participantId}`);
//Publishing the pubsub message with new mode
const onClickRequestJoinLiveStream = () => {
publish({
mode: "SIGNALLING_ONLY",
});
};
return (
<View
style={{
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
marginVertical: 8,
}}
>
<Text>{displayName}</Text>
<TouchableOpacity
onPress={() => {
onClickRequestJoinLiveStream();
}}
style={{
marginLeft: 12,
borderWidth: 1,
borderRadius: 12,
padding: 12,
}}
>
<Text>Request to join Livestream</Text>
</TouchableOpacity>
</View>
);
}
Step 3: Showing Viewer Request Dialog
After implementing the host's request for a viewer to join the livestream, display the viewer's request dialogue and switch the mode from SIGNALLING_ONLY
to SEND_AND_RECV
.
import { usePubSub } from "@videosdk.live/react-native-sdk";
import Video from "react-native-video";
import { Alert } from "react-native";
function ViewerView({}) {
const { hlsState, hlsUrls, localParticipantId, changeMode } = useMeeting();
usePubSub(`CHANGE_MODE_${localParticipantId}`, {
onMessageReceived: (data) => {
const { message, senderName } = data;
if (message.mode === "SEND_AND_RECV") {
showAlert(senderName);
}
},
});
const showAlert = (senderName) => {
Alert.alert(
"Permission",
`${senderName} has requested you to join as a speaker`,
[
{
text: "Reject",
onPress: () => console.log("Cancel Pressed"),
style: "cancel",
},
{
text: "Accept",
onPress: () => {
changeMode("SEND_AND_RECV");
},
},
]
);
};
return (
<SafeAreaView style={{ flex: 1 }}>
{hlsState == "HLS_PLAYABLE" ? (
<>
{/* Render VideoPlayer that will play `downstreamUrl`*/}
<Video
controls={true}
source={{
uri: hlsUrls.downstreamUrl,
}}
resizeMode={"stretch"}
style={{
flex: 1,
backgroundColor: "black",
}}
onError={(e) => console.log("error", e)}
/>
</>
) : (
<SafeAreaView
style={{ flex: 1, justifyContent: "center", alignItems: "center" }}
>
<Text style={{ fontSize: 20 }}>
HLS is not started yet or is stopped
</Text>
</SafeAreaView>
)}
</SafeAreaView>
);
}

Step 4: Pin the participant
To ensure the participant appears on the livestream, they have to be pinned. This can be achieved by listening to the callback on the onParticipantModeChanged
event of the useMeeting
hook.
function MeetingView() {
const mMeeting = useMeeting({});
///Here a reference to the meeting object is used because
//while referencing it in the callbacks its latest state has to be obtained.
const mMeetingRef = useRef();
useEffect(() => {
mMeetingRef.current = mMeeting;
}, [mMeeting]);
const { localParticipant, changeMode } = useMeeting({
onParticipantModeChanged: ({ participantId, mode }) => {
const localParticipant = mMeetingRef.current?.localParticipant;
if (participantId == localParticipant.id) {
if (mode == "SEND_AND_RECV") {
localParticipant.pin();
} else {
localParticipant.unpin();
}
}
},
});
return <>...</>;
}
For the complete source code, you can checkout our code sample
API Reference
The API references for all the methods utilized in this guide are provided below.
Got a Question? Ask us on discord