Estoy tratando de ordenar una matriz compleja. Esta matriz se toma con GraphQL de mi CMS sin cabeza de la siguiente manera:
query MyQuery { teams { id name match { teams { name } homePoints awayPoints date trophy } } }Ahora estoy mapeando todos los equipos y calculé los puntos totales de un equipo (dependiendo de si un equipo juega en casa o fuera) con lo siguiente:
<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>El resultado se muestra bien dentro de una tabla, excepto lo siguiente: no está ordenado. El equipo con la mayor cantidad de puntos debe estar en la parte superior de la tabla. ¿Cómo resolver esto?
Oh, ya veo, básicamente quieres ordenar la matriz. Sin embargo, no preparó la matriz antes de tiempo, ese es el problema en el que se mete.
Para resolver esto, primero preparemos la matriz.
// this the the teams with points // you did good job of processing it let teams = data.teams.map(...) // sort the array // please test the sorting order teams.sort(function(a, b) { return Math.sign(b.point - a.point) }) // this is the place for render return ( <Tbody> {teams.map(team => ( <Tr key={team.id}> ... </Tr> )} <Tbody> ) Una buena práctica general es que no traiga ningún código lógico a la capa de renderizado. En React , se trata de la línea del return , si puede poner la mayor parte de la lógica por encima de esa línea, lo ayudará a refactorizar su representación más adelante.
Para obtener un código limpio, cree algunas funciones auxiliares antes de la parte de procesamiento/retorno. Debería verse algo como esto:
// 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> }