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.
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:
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
.
const cameraTracks = useTracks([Track.Source.Camera]);<TrackLoop tracks={cameraTracks}><MyParticipantTile /></TrackLoop>;
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 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:
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 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() function to do so.
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.
// TrackLoop will use the default template.<TrackLoop trackRefs={tracks}/>// TrackLoop will use MyComponent as a template.<TrackLoop trackRefs={tracks}><MyComponent /></TrackLoop>