跳至主要内容
版本: v18.0.0

数组和列表

到目前为止,我们只处理了由它们组成的组件只有一个实例的组件。例如,我们只显示了一个新闻提要故事,而在这个故事中,只有一个作者,只有一个个人资料图片。让我们看看如何处理多个相同的东西。

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 键

此时,你应该在屏幕上看到多个故事!它开始看起来像一个真正的新闻提要应用程序了。

Multiple stories

但是,我们也收到了一个 React 警告,提示我们正在渲染一个没有提供键属性的组件数组。

React missing key warning

始终注意这个警告很重要,更具体地说,要将键基于显示事物的标识,而不是仅仅基于它们在数组中的索引。这允许 React 正确处理对列表中项目的重新排序和删除,因为它知道哪些项目是哪些,即使它们的顺序改变了。

幸运的是,GraphQL 节点通常都有 ID。我们可以简单地选择storyid字段,并将其用作键

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 列表用作构建块。

继续!