> ## Documentation Index
> Fetch the complete documentation index at: https://docs.daily.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Working with participants

> Read, filter, sort, and react to participant state in Daily React without over-rendering.

Participants are the core of any call UI. Daily React gives you a set of hooks for reading participant state, designed so that you subscribe to the smallest slice you need and re-render only when it changes.

## List participants

[`useParticipantIds`](/reference/daily-react/use-participant-ids) returns an array of participant session IDs and updates as people join and leave. It is the starting point for any grid or list:

```jsx theme={null}
import { useParticipantIds } from '@daily-co/daily-react';

function CallGrid() {
  const participantIds = useParticipantIds();
  return participantIds.map((id) => <Tile key={id} sessionId={id} />);
}
```

### Filter and sort

Pass `filter` and `sort` to scope the list. String-based filters and sorts are computed directly from the internal store and are cheaper than a custom function evaluated at runtime:

```jsx theme={null}
// Remote participants only, sorted by join time
const remoteIds = useParticipantIds({
  filter: 'remote',
  sort: 'joined_at',
});
```

Built-in filters are `'local'`, `'remote'`, `'screen'`, `'owner'`, and `'record'`; built-in sorts are `'joined_at'`, `'session_id'`, `'user_id'`, and `'user_name'`. For anything more specific, pass a function that receives the full [participant object](/reference/daily-js/instance-methods/participants):

```jsx theme={null}
const handRaisedIds = useParticipantIds({
  filter: (p) => Boolean(p.userData?.handRaised),
});
```

<Tip>
  Prefer the string filters and sorts when they fit. They run against the store and avoid re-evaluating a callback on every participant on every change.
</Tip>

`useParticipantIds` also accepts event callbacks (`onParticipantJoined`, `onParticipantLeft`, `onParticipantUpdated`, `onActiveSpeakerChange`) if you need to react to a change rather than just render the current list.

## Read a single property

[`useParticipantProperty`](/reference/daily-react/use-participant-property) reads one property (or a few) of a participant and re-renders only when that property changes. This is the workhorse hook for tiles:

```jsx theme={null}
import { useParticipantProperty } from '@daily-co/daily-react';

function Tile({ sessionId }) {
  const userName = useParticipantProperty(sessionId, 'user_name');
  const audioState = useParticipantProperty(sessionId, 'tracks.audio.state');
  return (
    <div>
      <span>{userName}</span>
      {audioState === 'off' && <MutedIcon />}
    </div>
  );
}
```

Dot paths reach nested properties (`'tracks.video.subscribed'`), and you can request several at once by passing an array:

```jsx theme={null}
const [isOwner, userName] = useParticipantProperty(sessionId, [
  'owner',
  'user_name',
]);
```

<Note>
  Use `useParticipantProperty` instead of the deprecated `useParticipant`, which returns the whole participant object and re-renders on any change to it. `useParticipant`, `useLocalParticipant`, and `useActiveParticipant` were all deprecated in 0.17.0 for this reason.
</Note>

## The local participant

You usually want the local participant's session ID, not the whole object. [`useLocalSessionId`](/reference/daily-react/use-local-session-id) gives you just that, and you compose it with the other hooks:

```jsx theme={null}
import { useLocalSessionId, useParticipantProperty } from '@daily-co/daily-react';

function LocalName() {
  const localSessionId = useLocalSessionId();
  const userName = useParticipantProperty(localSessionId, 'user_name');
  return <span>You are {userName}</span>;
}
```

## Who is speaking

[`useActiveSpeakerId`](/reference/daily-react/use-active-speaker-id) returns the session ID of the current active speaker, or `null` when nobody has spoken. Pass `ignoreLocal` to exclude yourself, or a `filter` to limit which participants can become the active speaker:

```jsx theme={null}
import { useActiveSpeakerId, DailyVideo } from '@daily-co/daily-react';

function Spotlight() {
  const activeSpeakerId = useActiveSpeakerId({ ignoreLocal: true });
  if (!activeSpeakerId) return null;
  return <DailyVideo sessionId={activeSpeakerId} type="video" />;
}
```

See [Active speaker and audio levels](/docs/daily-react/docs/active-speaker) for speaking indicators and volume meters.

## Count participants

[`useParticipantCounts`](/reference/daily-react/use-participant-counts) returns `present` and `hidden` counts. `hidden` counts participants with `hasPresence: false`, such as observers or bots:

```jsx theme={null}
import { useParticipantCounts } from '@daily-co/daily-react';

function Header() {
  const { present } = useParticipantCounts();
  return <span>{present} in call</span>;
}
```

## Choosing the right hook

| You need                             | Hook                                                                                                                                |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- |
| The list of participants to render   | [`useParticipantIds`](/reference/daily-react/use-participant-ids)                                                                   |
| One property of a participant        | [`useParticipantProperty`](/reference/daily-react/use-participant-property)                                                         |
| The local participant's session ID   | [`useLocalSessionId`](/reference/daily-react/use-local-session-id)                                                                  |
| The current speaker                  | [`useActiveSpeakerId`](/reference/daily-react/use-active-speaker-id)                                                                |
| Head counts                          | [`useParticipantCounts`](/reference/daily-react/use-participant-counts)                                                             |
| To admit or deny people in the lobby | [`useWaitingParticipants`](/reference/daily-react/use-waiting-participants) (see [Permissions](/docs/daily-react/docs/permissions)) |

## Next steps

<CardGroup cols={2}>
  <Card title="Rendering media" icon="video" href="/docs/daily-react/docs/rendering-media">
    Turn participant IDs into video and audio.
  </Card>

  <Card title="Active speaker and audio levels" icon="waveform-lines" href="/docs/daily-react/docs/active-speaker">
    Highlight whoever is talking.
  </Card>
</CardGroup>
