Overview
The WellPlayed React SDK provides the useTournamentTeams hook for fetching tournament teams along with their members and player profiles. This hook automatically combines team data with player information for easy rendering.
useTournamentTeams Hook
The useTournamentTeams hook fetches all teams for a tournament, including team members and their associated player profiles.
Basic Usage
import { useTournamentTeams } from '@well-played.gg/react-sdk' ;
import { useParams } from 'react-router-dom' ;
const TournamentTeams = () => {
const { id } = useParams <{ id : string }>();
const { loading , results : teams } = useTournamentTeams ({
tournamentId: id ?? '' ,
});
if ( loading ) {
return < div > Loading... </ div > ;
}
return (
< div >
{ teams . map (( team ) => (
< div key = { team . id } >
< h3 > { team . name } </ h3 >
< p > Status: { team . status } </ p >
< ul >
{ team . members . map (( member ) => (
< li key = { member . playerProfileId } >
{ member . player . username } - { member . status }
</ li >
)) }
</ ul >
</ div >
)) }
</ div >
);
};
The hook automatically fetches player profiles for all team members, so you don’t need to make separate queries (source: packages/react-sdk/src/api/hooks/teams.hook.ts:84).
Parameters
The ID of the tournament to fetch teams for
Whether to skip fetching the data
Filter teams by their status. Possible values:
REGISTERED - Team has registered but not confirmed
CONFIRMED - Team is confirmed and active
AWAITING_FOR_PRESENCE_CONFIRMATION - Waiting for presence check
Other status values as defined by your tournament configuration
Return Value
Array of tournament teams with the following structure:
id - Team ID
name - Team name
status - Team status
members - Array of team members with player profiles
Indicates whether the data is currently being fetched. This is true while fetching both teams and player profiles.
Team Data Structure
Each team object contains complete member information:
type Team = {
id : string ;
name : string ;
status : 'REGISTERED' | 'CONFIRMED' | 'AWAITING_FOR_PRESENCE_CONFIRMATION' ;
members : {
status : string ;
playerProfileId : string ;
player : {
id : string ;
username : string ;
ownerId : string ;
customFields ?: Array <{
property : string ;
value : string ;
}>;
identities ?: Array <{
providerId : string ;
properties : Array <{
property : string ;
value : string ;
}>;
}>;
};
}[];
};
Filtering Teams by Status
You can filter teams by their status to show only confirmed or registered teams:
const ConfirmedTeams = ({ tournamentId } : { tournamentId : string }) => {
const { loading , results : teams } = useTournamentTeams ({
tournamentId ,
status: 'CONFIRMED' ,
});
return (
< div >
< h2 > Confirmed Teams ( { teams . length } ) </ h2 >
{ teams . map (( team ) => (
< TeamCard key = { team . id } team = { team } />
)) }
</ div >
);
};
The hook automatically filters for members with ACCEPTED status (source: packages/react-sdk/src/api/hooks/teams.hook.ts:16).
Complete Example
Here’s a real-world example from the WellPlayed demo application showing how to organize teams by status (source: demo/src/features/tournaments/tournament-teams.tsx:1):
import { useTournamentTeams } from '@well-played.gg/react-sdk' ;
import React from 'react' ;
import { useParams } from 'react-router-dom' ;
export const TournamentTeams = () => {
const { id } = useParams <{ id : string }>();
const { loading , results : teams } = useTournamentTeams ({
tournamentId: id ?? '' ,
});
if ( loading ) {
return < div > Loading... </ div > ;
}
const confirmedTeams = teams ?. filter (( team ) => team . status === 'CONFIRMED' );
const registeredTeams = teams ?. filter (
( team ) =>
team . status === 'REGISTERED' ||
team . status === 'AWAITING_FOR_PRESENCE_CONFIRMATION' ,
);
return (
< div >
< h1 > Confirmed teams </ h1 >
{ confirmedTeams ?. map (( team ) => (
< div key = { team . id } >
{ team . name }
< br />
{ team . members . map (
( member ) => ` ${ member . player ?. username } - ${ member . status } ` ,
) }
</ div >
)) }
< h1 > Registered teams </ h1 >
{ registeredTeams ?. map (( team ) => (
< div key = { team . id } >
{ team . name }
< br />
{ team . members . map (
( member ) => ` ${ member . player ?. username } - ${ member . status } ` ,
) }
</ div >
)) }
</ div >
);
};
Working with Team Members
Team members include both member status and complete player profile information:
Access Member Status
Each member has their own status indicating their relationship with the team: { team . members . map (( member ) => (
< div key = { member . playerProfileId } >
< p > Status: { member . status } </ p >
</ div >
))}
Access Player Information
The player object contains complete profile data: { team . members . map (( member ) => (
< div key = { member . playerProfileId } >
< h4 > { member . player . username } </ h4 >
< p > Player ID: { member . player . id } </ p >
</ div >
))}
Access Custom Fields
Player custom fields are available through the member’s player object: { team . members . map (( member ) => (
< div key = { member . playerProfileId } >
{ member . player . customFields ?. map (( field ) => (
< span key = { field . property } >
{ field . property } : { field . value }
</ span >
)) }
</ div >
))}
GraphQL Query
The useTournamentTeams hook uses the following GraphQL query:
query tournamentTeam (
$tournamentId : ID !
$page : PageInfo !
$status : TournamentTeamStatus
) {
tournamentTeams (
tournamentId : $tournamentId
page : $page
memberStatus : ACCEPTED
status : $status
) {
pageInfo {
endCursor
hasNextPage
}
nodes {
id
name
status
members {
status
playerProfileId
}
}
}
}
The hook automatically handles pagination and fetches all teams regardless of the total count (source: packages/react-sdk/src/api/hooks/teams.hook.ts:65).
Team Status Values
Teams can have different statuses throughout a tournament lifecycle:
REGISTERED Team has registered for the tournament but hasn’t been confirmed yet.
CONFIRMED Team is confirmed and actively participating in the tournament.
AWAITING_FOR_PRESENCE_CONFIRMATION Team is waiting for presence confirmation before matches begin.
Advanced Usage
Combining with Tournament Steps
You can use teams data alongside tournament step data:
import { useTournamentStep , useTournamentTeams } from '@well-played.gg/react-sdk' ;
const TournamentBracket = ({ tournamentId , stepId }) => {
const { loading : loadingStep , groups } = useTournamentStep ({
tournamentId ,
stepId ,
});
const { loading : loadingTeams , results : teams } = useTournamentTeams ({
tournamentId ,
status: 'CONFIRMED' ,
});
if ( loadingStep || loadingTeams ) {
return < div > Loading... </ div > ;
}
// Render bracket with team information
};
Both hooks will be loading simultaneously. Make sure to check both loading states before rendering.
Filtering and Sorting
Create custom filters and sorts for team lists:
const TeamList = ({ tournamentId } : { tournamentId : string }) => {
const { loading , results : teams } = useTournamentTeams ({ tournamentId });
if ( loading ) return < div > Loading... </ div > ;
// Sort teams by name
const sortedTeams = [ ... teams ]. sort (( a , b ) =>
a . name . localeCompare ( b . name )
);
// Filter teams with full rosters
const fullTeams = teams . filter (
( team ) => team . members . length >= 5
);
return (
< div >
< h2 > All Teams (Sorted) </ h2 >
{ sortedTeams . map (( team ) => (
< TeamCard key = { team . id } team = { team } />
)) }
< h2 > Full Rosters </ h2 >
{ fullTeams . map (( team ) => (
< TeamCard key = { team . id } team = { team } />
)) }
</ div >
);
};
Best Practices
Always check for empty results and provide helpful feedback: if ( ! loading && teams . length === 0 ) {
return < div > No teams registered yet </ div > ;
}
Filter teams on the server side using the status parameter instead of filtering in your component: // Good - Server-side filtering
const { results } = useTournamentTeams ({
tournamentId ,
status: 'CONFIRMED' ,
});
// Less efficient - Client-side filtering
const { results } = useTournamentTeams ({ tournamentId });
const confirmed = results . filter ( t => t . status === 'CONFIRMED' );
Handle Missing Player Data
Use optional chaining when accessing player data to handle edge cases: { team . members . map (( member ) => (
< div key = { member . playerProfileId } >
{ member . player ?. username ?? 'Unknown Player' }
</ div >
))}