LiveKit docs › Concepts › Loop components

---

# Loop Components

Loop components are a thin layer on top of basic JS for-loops, creating a dedicated React context (`TrackRefContext` or `ParticipantContext`) on each iteration. They accept a child component to use as a template for all elements of the passed array.

## Track Loop

The `TrackLoop` component loops over an array of `TrackReferences` and creates a `TrackRefContext` for every item. We can use it for example to loop over all camera tracks of the room and render them with the `ParticipantTile` component.

```tsx
const cameraTracks = useTracks([Track.Source.Camera]);

<TrackLoop tracks={cameraTracks}>
  <ParticipantTile />
</TrackLoop>;

```

We can nest any other component inside the loop if we need more flexibility or control. If we want to build our own ParticipantTile for full control over styling, we could do this:

```tsx
function MyParticipantTile() {
  return (
    <div style={{ position: 'relative' }}>
      <TrackRefContext.Consumer>
        {(track) => track && <VideoTrack {...track} />}
      </TrackRefContext.Consumer>
    </div>
  );
}

```

And then pass it as a template to the `TrackLoop`.

```tsx
const cameraTracks = useTracks([Track.Source.Camera]);

<TrackLoop tracks={cameraTracks}>
  <MyParticipantTile />
</TrackLoop>;

```

> 💡 **Tip**
> 
> How is this different from the `ParticipantLoop`? One Participant can have more than one Track. E.g. it is not uncommon to loop over all camera as well as screen share tracks.

For more details check out the [TrackLoop](https://docs.livekit.io/reference/components/react/component/trackloop.md) page.

## Participant Loop

The `ParticipantLoop` component loops over an array of Participants and creates a distinct `ParticipantContext` for each child. As an example, to render a list of all the participants' names in the room, we could simply do the following:

```tsx
import { useParticipants, ParticipantLoop, ParticipantName } from `@livekit/react`;

const participants = useParticipants();

<ParticipantLoop participants={participants}>
  // ParticipantName is a LiveKit component that uses the ParticipantContext
  // to render the name of a participant.
  <ParticipantName />
</ParticipantLoop>

```

For more details take a look at the [ParticipantLoop](https://docs.livekit.io/reference/components/react/component/participantloop.md) API page.

## Filter Loops

In order to loop over only a subset of the tracks, you will need to filter the tracks before passing them as a property to the `TrackLoop`. Use the standard [Array.filter()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) function to do so.

```tsx
const tracks = useTracks([
  { source: Track.Source.Camera, withPlaceholder: true },
  { source: Track.Source.ScreenShare, withPlaceholder: false },
]);

const screenShareTracks = tracks.filter(
  (track) => track.publication.source === Track.Source.ScreenShare,
);

// Loop only over screen share tracks.
<TrackLoop tracks={screenShareTracks}>
  <ParticipantTile />
</TrackLoop>;

```

## Default Template

Both loops have in common that they only accept one or no child. If no child is provided the default template is used. If a child is provided, it is used as a template for every item of the loop.

```tsx
// TrackLoop will use the default template.
<TrackLoop trackRefs={tracks}/>

// TrackLoop will use MyComponent as a template.
<TrackLoop trackRefs={tracks}>
  <MyComponent />
</TrackLoop>

```

---

This document was rendered at 2026-06-07T11:32:47.314Z.
For the latest version of this document, see [https://docs.livekit.io/reference/components/react/concepts/loops.md](https://docs.livekit.io/reference/components/react/concepts/loops.md).

To explore all LiveKit documentation, see [llms.txt](https://docs.livekit.io/llms.txt).