我正在嘗試對復雜陣列進行排序。這個陣列是從我的無頭 CMS 中使用 GraphQL 抓取的,如下所示:
query MyQuery {
teams {
id
name
match {
teams {
name
}
homePoints
awayPoints
date
trophy
}
}
}
現在我正在繪制所有球隊并計算一個球隊的總分(取決于球隊是主場還是客場),如下所示:
<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>
結果很好地顯示在表格中,但以下情況除外:它沒有排序。得分最高的球隊應該排在積分榜的首位。如何解決這個問題?
uj5u.com熱心網友回復:
對于干凈的代碼,在渲染/回傳部分之前創建一些輔助函式。它應該看起來像這樣:
// 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>
}
uj5u.com熱心網友回復:
哦,我明白了,您基本上想對陣列進行排序。然而你沒有提前準備好陣列,這就是你自己陷入的麻煩。
為了解決這個問題,讓我們先準備陣列。
// 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>
)
一般的好做法是,不要將任何邏輯代碼帶入渲染層。在React 中,它是關于 的那一行return,如果您可以將大部分邏輯放在該行之上,它將幫助您稍后重構您的渲染。
uj5u.com熱心網友回復:
我建議創建一個輔助函式來計算團隊的分數。
// outside the component
function calculatePoints(team) {
return team.match
.map((match) => {
// introduction of variable for code clarity (self explaining code)
const isHomeMatch = match.teams[0].name === team.name;
return isHomeMatch ? match.homePoints : match.awayMatch;
})
.reduce((total, points) => total points, 0);
}
為了防止計算每個渲染,您可以使用useMemo存盤每個團隊的計算點。您可以將它們放在 a 中Map以便快速訪問。
// inside the component
const points = useMemo(() => {
const teams = data?.teams || []; // default to an empty array if not present
return new Map(teams.map(team => [team, calculatePoints(team)]));
}, [data?.teams]);
然后data.teams根據每個團隊的分數創建一個排序的副本。請注意,對sort()元素進行原地排序(也就是改變陣列)。出于這個原因,您應該創建一個副本,以便原始陣列保持不變。
// inside the component
const sortedTeams = useMemo(() => {
const teams = data?.teams || []; // default to an empty array if not present
// create a shallow copy because `sort()` sorts the elements in place
const sorted = Array.from(teams);
sorted.sort((a, b) => points.get(b) - points.get(a)); // desc = b - a
return sorted;
}, [data?.teams]);
最后,使用sortedTeams代替作為data.teams渲染函式的回傳值。
<Tbody>
{!fetching && sortedTeams.map((team, i) => (
<Tr key={team.id}>
<Td>{i 1}</Td>
<Td>{team.name}</Td>
<Td>{points.get(team)}</Td>
</Tr>
))}
</Tbody>
data?.teamsteams如果資料不為空(null或undefined),則只會訪問該屬性。如果為空,undefined則回傳。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/352815.html
標籤:javascript 数组 反应 排序
上一篇:Uncaught(inpromise)SyntaxError:Unexpectedtoken<inJSONatposition0fromSpringBootAPI
