陣列與列表
到目前為止,我們只處理了組件中只有單個實例的組件。例如,我們只顯示單個新聞提要故事,並且在該故事中,只有一個具有單個個人資料圖片的作者。讓我們看看如何處理多個相同的事物。
GraphQL 包含對陣列的支援,在 GraphQL 中稱為列表。一個欄位不僅可以是單個純量值,還可以是它們的陣列,或者不僅是單個邊緣,還可以是邊緣的陣列。Schema 指定每個欄位是否為列表,但奇怪的是,GraphQL 查詢語法並不區分選擇單個欄位和選擇列表 - 這是 GraphQL 回應應該與查詢具有相同形狀的設計原則的一個奇怪例外。
請求
query MyQuery {
viewer {
contacts { // List of edges
id // field on a single item
name
}
}
}
回應
{
viewer: {
contacts: [ // array in response
{
id: "123",
name: "Chris",
},
{
id: "789",
name: "Sue",
}
]
}
}
碰巧的是,我們的範例應用程式中的 schema 有一個 topStories
欄位,該欄位返回故事列表,而不是我們目前使用的僅返回一個故事的 topStory
欄位。
為了在我們的新聞提要上顯示多個故事,我們只需要修改 Newsfeed.tsx
以使用 topStories
。
步驟 1 — 在片段中選擇列表
打開 Newsfeed.tsx
並找到 NewsfeedQuery
。將 topStory
替換為 topStories
,然後執行 npm run relay
。
const NewsfeedQuery = graphql`
query NewsfeedQuery {
topStories {
...StoryFragment
}
}
`;
步驟 2 — 在組件中映射列表
在 Newsfeed
組件中,data.topStories
現在將會是一個片段引用陣列,每個片段引用都可以傳遞給 Story
子組件以呈現該故事
export default function Newsfeed({}) {
const data = useLazyLoadQuery<NewsfeedQueryType>(NewsfeedQuery, {});
const stories = data.topStories;
return (
<div className="newsfeed">
{stories.map(story => <Story story={story} />)}
</div>
);
}
步驟 3 — 根據節點 ID 新增 React 金鑰
到目前為止,您應該在螢幕上看到多個故事了!它開始看起來像一個適當的新聞提要應用程式。
但是,我們也收到一個 React 警告,警告我們正在呈現一個沒有提供 key 屬性的組件陣列。
始終要注意這個警告,更具體來說,要根據顯示的事物的身分來建立金鑰,而不僅僅是它們在陣列中的索引。這允許 React 正確處理重新排序和從列表中刪除項目,因為它知道哪些項目是什麼,即使它們的順序發生變化。
幸運的是,GraphQL 節點通常具有 ID。我們可以簡單地選擇 story
的 id
欄位並將其用作金鑰
const NewsfeedQuery = graphql`
query NewsfeedQuery {
topStories {
id
...StoryFragment
}
}
`;
...
export default function Newsfeed({}) {
const data = useLazyLoadQuery<NewsfeedQueryType>(NewsfeedQuery, {});
const stories = data.topStories;
return (
<div className="newsfeed">
{stories.map(story => (
<Story
key={story.id}
story={story}
/>
)}
</div>
);
}
有了這個,我們在螢幕上就有了一系列故事。值得指出的是,在這裡我們在查詢的同一位置混合了個別欄位和片段展開。這表示 Newsfeed 可以讀取它關心的欄位(直接從 useLazyLoadQuery
讀取),而 Story 可以讀取它關心的欄位(透過 useFragment
讀取)。同一個物件同時包含 Newsfeed 的選定欄位 id
,並且也是 StoryFragment
的片段金鑰。
GraphQL 列表只是處理事物集合的最基本方式。我們稍後將在教學中使用它們來進行分頁和無限捲動,使用一個稱為「連接」的特殊系統。在大多數需要處理項目集合的情況下,您都應該使用「連接」,儘管您仍然會使用 GraphQL 列表作為基礎。
繼續前進!