I’m trying to sort a complex array. This array is grabbed with GraphQL from my headless CMS as follows:
query MyQuery {
teams {
id
name
match {
teams {
name
}
homePoints
awayPoints
date
trophy
}
}
}
Now I’m mapping through all the teams and calculated the total points of a team (depending whether a team is playing home or away) with the following:
<Tbody>
{!fetching && data.teams.map((team, i) => {
const points = team.match.map(match => match.teams[0].name === team.name ? match.homePoints : match.awayPoints).reduce((a, b) => a + b, 0)
return (
<Tr key={team.id}>
<Td>{i + 1}</Td>
<Td>{team.name}</Td>
<Td>{points}</Td>
</Tr>
)
})}
</Tbody>
The result is displayed well within a table, except the following: it is not sorted. The team with the highest amount of points should be on the top of the table. How to solve this?
>Solution :
For a clean code, create a few helper functions before the render / return part. It should looks something like this:
// Util functions outside component
const withPoints = (team, i) => {
const points = team.match.map(match =>
match.teams[0].name === team.name ? match.homePoints :
match.awayPoints).reduce((a, b) => a + b, 0)
return {team, points}
};
const byPoints = (a, b) => b.points - a.points
// My component
const MyComponent = ({fetching, data}) => {
// temporary assignment in component body to make the JSX part cleaner
const teams = fetching ?
data.teams
.map(withPoints)
.sort(byPoints)
: null
return <Tbody>
{teams && teams.map((t, i) => (
<Tr key={t.team.id}>
<Td>{i + 1}</Td>
<Td>{t.team.name}</Td>
<Td>{t.points}</Td>
</Tr>
))}
</Tbody>
}