数组和列表
到目前为止,我们只处理了由它们组成的组件只有一个实例的组件。例如,我们只显示了一个新闻提要故事,而在这个故事中,只有一个作者,只有一个个人资料图片。让我们看看如何处理多个相同的东西。
GraphQL 包含对数组的支持,在 GraphQL 中称为列表。一个字段不仅可以是一个标量值,也可以是标量值的数组,不仅可以是一个边缘,也可以是边缘的数组。模式会指定每个字段是否是列表,但奇怪的是,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",
}
]
}
}
碰巧,我们示例应用程序中的模式有一个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 警告,提示我们正在渲染一个没有提供键属性的组件数组。
始终注意这个警告很重要,更具体地说,要将键基于显示事物的标识,而不是仅仅基于它们在数组中的索引。这允许 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 列表用作构建块。
继续!