Call & Participant State

You can access call, participant and client state using hooks. These hooks are reactive (their value is updated on WebSocket events and API calls).

Call state

To observe call state you need to provide a Call instance to the StreamCall component.

For the best experience, please make sure that the provided Call instance is loaded and connected to our backend: Load Call.

Otherwise, call.state and the call state hooks will provide empty values.

Let’s see an example where we use the useCall, useCallCallingState and useParticipants hooks to display some basic information about the call:

import {
  Call,
  useCall,
  useCallStateHooks,
} from '@stream-io/video-react-native-sdk';

export default function MyApp() {
  let call: Call;

  return (
    <StreamCall call={call}>
      <MyCallUI />
    </StreamCall>
  );
}

const MyCallUI = () => {
  const call = useCall();

  const { useCallCallingState, useParticipants } = useCallStateHooks();
  const callingState = useCallCallingState();
  const participants = useParticipants();

  return (
    <div>
      <div>Call: {call?.cid}</div>
      <div>State: {callingState}</div>
      <div>Participants: {participants.length}</div>
    </div>
  );
};

This approach makes it possible to access the call state and be notified about changes anywhere in your application without having to manually subscribe to WebSocket events.

The StreamCall component is a context provider that makes the call state available to all child components. The useCall hook returns the Call instance that is registered with StreamCall. You need the Call instance to initiate API calls.

Call State Hooks

Here is an excerpt of the available call state hooks:

NameDescription
useCallThe Call instance that is registered with StreamCall. You need the Call instance to initiate API calls.
useCallBlockedUserIdsThe list of blocked user IDs.
useCallCallingStateProvides information about the call state. For example, RINGING, JOINED or RECONNECTING.
useCallCreatedAtThe time the call was created.
useCallCreatedByThe user that created the call.
useCallCustomDataThe custom data attached to the call.
useCallEgressThe egress information of the call.
useCallEndedByThe user that ended the call.
useCallIngressThe ingress information of the call.
useCallMembersThe list of call members
useCallSessionThe information for the current call session.
useCallSettingsThe settings of the call.
useCallStartedAtThe actual start time of the current call session.
useCallStartsAtThe scheduled start time of the call.
useCallStatsReportWhen stats gathering is enabled, this observable will emit a new value at a regular (configurable) interval.
useCallThumbnailThe thumbnail of the call.
useCallUpdatedAtThe time the call was last updated.
useCameraStateThe camera state of the local participant.
useDominantSpeakerThe participant that is the current dominant speaker of the call.
useHasOngoingScreenShareIt will return true if at least one participant is sharing their screen.
useHasPermissionsReturns true if the local participant has all the given permissions.
useIsCallHLSBroadcastingInProgressIt’s true if the call is being broadcasted in HLS mode.
useIsCallLiveIt’s true if the call is currently live.
useIsCallRecordingInProgressIt’s’ true if the call is being recorded.
useIsCallTranscribingInProgressIt’s true if the call is being transcribed.
useMicrophoneStateThe microphone state of the local participant.
useOwnCapabilitiesThe capabilities of the local participant.
useScreenShareStateThe screen share state of the local participant.
useSpeakerStateThe speaker state of the local participant.
useIncomingVideoSettingsThe state of manual overrides to incoming video quality.

In your IDE of choice, you can see the full list if you de-structure the useCallStateHooks object:

import { useCallStateHooks } from '@stream-io/video-react-native-sdk';

const {
  useCallMembers,
  useDominantSpeaker,
  useParticipants,
  useLocalParticipant,
  useIsCallRecordingInProgress,
  // ...
} = useCallStateHooks();

Participant state

If you want to display information about the joined participants of the call you can use these hooks:

NameDescription
useLocalParticipantThe local participant is the logged-in user.
useRemoteParticipantsAll participants except the local participant.
useParticipantsAll participants, including local and remote participants.
useParticipantCountThe approximate participant count of the active call. This includes the anonymous users as well, it is computed on the server-side.
useAnonymousParticipantCountThe approximate participant count of anonymous users in the active call.
import {
  useCallStateHooks,
  StreamCall,
} from '@stream-io/video-react-native-sdk';

export default function App() {
  let call: call;

  return (
    <StreamCall call={call}>
      <MyCallUI />
    </StreamCall>
  );
}

const MyCallUI = () => {
  const { useLocalParticipant, useParticipantCount } = useCallStateHooks();
  const participantCount = useParticipantCount();
  const localParticipant = useLocalParticipant();

  return (
    <View>
      <Text>Number of participants: {participantCount}</Text>
      <Text>Session ID: {localParticipant.sessionId}</Text>
    </View>
  );
};

The StreamVideoParticipant object contains the following information:

NameDescription
audioLevelThe audio level of the participant (determined on the server).
audioStreamThe published audio MediaStream.
audioVolumeThe audio volume level of the participant (overridable local audioVolume level).
connectionQualityThe participant’s connection quality.
customThe participant’s custom data. Comes from the custom field of the user object.
imageThe image of the participant.
isDominantSpeakerIt’s true if the participant is the current dominant speaker in the call.
isLocalParticipantIt’s true if the participant is the local participant.
isSpeakingIt’s true if the participant is currently speaking.
joinedAtThe time the participant joined the call.
nameThe name of the participant.
pinHolds pinning information.
publishedTracksThe track types the participant is currently publishing
reactionThe last reaction this user has sent to this call.
rolesThe roles of the participant in this call.
sessionIdThe identifier of the participant within the existing call session
screenShareAudioStreamThe published screen share audio MediaStream.
screenShareStreamThe published screen share MediaStream.
userIdThe user ID of the participant.
videoStreamThe published video MediaStream.
viewportVisibilityStateThe viewport visibility state of the participant.

The SDK also provides a few utility functions that help you to work with participants:

import {
  hasAudio,
  hasVideo,
  hasScreenShare,
  hasScreenShareAudio,
  isPinned,
  useCallStateHooks,
} from '@stream-io/video-react-native-sdk';

// example usage
const { useParticipants } = useCallStateHooks();

// check if the participant has audio, video, screen share or screen share audio
const [participant] = useParticipants();
const hasAudioOn = hasAudio(participant);
const hasVideoOn = hasVideo(participant);
const hasScreenShareOn = hasScreenShare(participant);
const hasScreenShareAudioOn = hasScreenShareAudio(participant);
const isPinnedOn = isPinned(participant);

// participants with a specific role
const hosts = participants.filter((p) => p.roles.includes('host'));

// participants that publish video and audio
const videoParticipants = participants.filter(
  (p) => hasVideo(p) && hasAudio(p)
);

In a call with many participants, the list returned by the useParticipants call state hook is truncated to 250 participants. The participants who are publishing video, audio, or screen sharing have priority over the other participants in the list. This means, for example, that in a livestream with one host and many viewers, the host is guaranteed to be in the list.

Client state

To observe client state you need to provide a StreamVideoClient instance to the StreamVideo context provider. If you want to observe the connected user you can use the useConnectedUser hook.

Let’s see an example:

import {
  useConnectedUser,
  StreamVideo,
  StreamVideoClient,
} from '@stream-io/video-react-native-sdk';

export default function App() {
  let client: StreamVideoClient;

  return (
    <StreamVideo client={client}>
      <MyHeader />
    </StreamVideo>
  );
}

const MyHeader = () => {
  const user = useConnectedUser();
  return <Text>{user ? `Logged in: ${user.name}` : 'Logged out'}</Text>;
};

This approach makes it possible to access the client state and be notified about changes anywhere in your application without having to manually subscribe to WebSocket events.

Here is the list of client-state hooks:

NameDescription
useStreamVideoClientThe StreamVideoClient instance.
useConnectedUserReturns the connected user. Holds the server-side data of the connected user.
useCallsA list of all tracked calls. These calls can be outgoing (I have called somebody) or incoming (somebody has called me). Loaded calls (call.get()) are also part of this list.

The connectedUser object contains the following properties:

NameDescription
created_atThe time the user was created.
customCustom user data.
deleted_atThe time the user was deleted.
devicesThe registered push notification devices of the user.
idThe id of the user.
imageThe profile image of the user.
nameThe name of the user.
roleThe role of the user.
teamsThe teams the user belongs to.
updated_atThe time when the user was updated.
© Getstream.io, Inc. All Rights Reserved.