fetchMore return 数据如何到组件?
How does fetchMore return data to the component?
我正在尝试使用 React Apollo (https://www.apollographql.com/docs/react/data/pagination/#cursor-based) 进行基于游标的分页示例,但我正在努力解决 我呈现原始数据的组件如何获得新的(附加的)数据.
这是我们获取原始数据并将其传递给组件的方式:
const { data: { comments, cursor }, loading, fetchMore } = useQuery(
MORE_COMMENTS_QUERY
);
<Comments
entries={comments || []}
onLoadMore={...}
/>
我不确定 fetchMore
函数是如何工作的。
onLoadMore={() =>
fetchMore({
query: MORE_COMMENTS_QUERY,
variables: { cursor: cursor },
updateQuery: (previousResult, { fetchMoreResult }) => {
const previousEntry = previousResult.entry;
const newComments = fetchMoreResult.moreComments.comments;
const newCursor = fetchMoreResult.moreComments.cursor;
return {
// By returning `cursor` here, we update the `fetchMore` function
// to the new cursor.
cursor: newCursor,
entry: {
// Put the new comments in the front of the list
comments: [...newComments, ...previousEntry.comments]
},
__typename: previousEntry.__typename
};
}
})
}
据我了解,是的,一旦我的组件调用此 onLoadMore
函数(例如使用按钮的 onClick),它将基于新光标获取数据。
我的问题是这样的。很抱歉,如果这太简单了,我不了解一些基本的东西。
组件如何获取新数据?
我知道数据在那里,因为我控制台记录了 newComments
(在我的例子中,它不是 newComments,但你明白了。)而且我看到了新数据!但是那些新的注释,它们如何返回到需要数据的组件呢?如果我再次点击该按钮,它仍然停留在与之前相同的光标上。
我在这里错过了什么?
在 updateQuery
函数中,您可以修改(覆盖)当前查询的结果。同时,您的组件订阅了查询并将获得新结果。让我们来玩一下:
- 你的组件是第一次渲染,组件会订阅查询,如果有的话,会从缓存中接收当前的查询结果。如果不是,查询将开始从 GraphQL 服务器获取,并且您的组件会收到有关加载状态的通知。
- 如果获取查询,您的组件将在结果出现后获取数据。它现在显示前 x 个结果。在缓存中为您的查询字段创建一个条目。这可能看起来像这样:
{
"Query": {
"cursor": "cursor1",
"entry": { "comments": [{ ... }, { ... }] }
}
}
// normalised
{
"Query": {
"cursor": "cursor1",
"entry": Ref("Entry:1"),
}
"Entry:1": {
comments: [Ref("Comment:1"), Ref("Comment:2")],
},
"Comment:1": { ... },
"Comment:2": { ... }
}
- 用户点击加载更多,您的查询被再次获取,但带有光标值。游标告诉 API 它应该从哪个条目开始 returning 值。在我们的示例中
Comment
之后,id 2
.
- 查询结果进来,你使用
updateQuery
函数手动更新缓存中的查询结果。这里的想法是我们要将旧结果(列表)与新结果列表合并。我们已经获取了 2 条评论,现在我们要添加这两条新评论。您必须 return 一个结果,该结果是两个查询的组合结果。为此,我们需要更新光标值(以便我们可以再次单击“加载更多”并连接评论列表。该值已写入缓存,我们的规范化缓存现在如下所示:
{
"Query": {
"cursor": "cursor2",
"entry": { "comments": [{ ... }, { ... }, { ... }, { ... }] }
}
}
// normalised
{
"Query": {
"cursor": "cursor2",
"entry": Ref("Entry:1"),
}
"Entry:1": {
comments: [Ref("Comment:1"), Ref("Comment:2"), Ref("Comment:3"), Ref("Comment:4")],
},
"Comment:1": { ... },
"Comment:2": { ... },
"Comment:3": { ... },
"Comment:4": { ... }
}
- 由于您的组件订阅了查询,它将使用缓存中的新查询结果重新呈现!数据显示在 UI 中,因为我们合并了查询,以便组件获取新数据,就像结果首先包含所有四个评论一样。
这取决于你如何处理偏移量。我将尝试为您简化示例。
这是我使用成功的简化组件:
const PlayerStats = () => {
const { data, loading, fetchMore } = useQuery(CUMULATIVE_STATS, {
variables: sortVars,
})
const players = data.GetCumulativeStats
const loadMore = () => {
fetchMore({
variables: { offset: players.length },
updateQuery: (prevResult, { fetchMoreResult }) => {
if (!fetchMoreResult) return prevResult
return {
...prevResult,
GetCumulativeStats: [
...prevResult.GetCumulativeStats,
...fetchMoreResult.GetCumulativeStats,
],
}
},
})
}
我的 CUMULATIVE_STATS
默认查询 returns 50 行。我将该结果数组的长度作为 offset
传递给我的 fetchMore
查询。所以当我用fetchMore
执行CUMULATIVE_STATS
时,查询的变量都是sortVars
和offset
.
我在后端的解析器处理 offset
,因此如果它是,例如,50,它会忽略查询的前 50 个结果,returns 从那里开始的下一个 50(即第 51-100 行)。
然后在 updateQuery
中我有两个对象可用:prevResult
和 fetchMoreResult
。在这一点上,我只是使用扩展运算符将它们组合起来。如果没有新的结果被 returned,我 return 以前的结果。
当我再取一次的时候,players.length
的结果就变成了100,而不是50。这就是我的新偏移量,下次调用fetchMore
的时候会查询到新的数据。
我正在尝试使用 React Apollo (https://www.apollographql.com/docs/react/data/pagination/#cursor-based) 进行基于游标的分页示例,但我正在努力解决 我呈现原始数据的组件如何获得新的(附加的)数据.
这是我们获取原始数据并将其传递给组件的方式:
const { data: { comments, cursor }, loading, fetchMore } = useQuery(
MORE_COMMENTS_QUERY
);
<Comments
entries={comments || []}
onLoadMore={...}
/>
我不确定 fetchMore
函数是如何工作的。
onLoadMore={() =>
fetchMore({
query: MORE_COMMENTS_QUERY,
variables: { cursor: cursor },
updateQuery: (previousResult, { fetchMoreResult }) => {
const previousEntry = previousResult.entry;
const newComments = fetchMoreResult.moreComments.comments;
const newCursor = fetchMoreResult.moreComments.cursor;
return {
// By returning `cursor` here, we update the `fetchMore` function
// to the new cursor.
cursor: newCursor,
entry: {
// Put the new comments in the front of the list
comments: [...newComments, ...previousEntry.comments]
},
__typename: previousEntry.__typename
};
}
})
}
据我了解,是的,一旦我的组件调用此 onLoadMore
函数(例如使用按钮的 onClick),它将基于新光标获取数据。
我的问题是这样的。很抱歉,如果这太简单了,我不了解一些基本的东西。
组件如何获取新数据?
我知道数据在那里,因为我控制台记录了 newComments
(在我的例子中,它不是 newComments,但你明白了。)而且我看到了新数据!但是那些新的注释,它们如何返回到需要数据的组件呢?如果我再次点击该按钮,它仍然停留在与之前相同的光标上。
我在这里错过了什么?
在 updateQuery
函数中,您可以修改(覆盖)当前查询的结果。同时,您的组件订阅了查询并将获得新结果。让我们来玩一下:
- 你的组件是第一次渲染,组件会订阅查询,如果有的话,会从缓存中接收当前的查询结果。如果不是,查询将开始从 GraphQL 服务器获取,并且您的组件会收到有关加载状态的通知。
- 如果获取查询,您的组件将在结果出现后获取数据。它现在显示前 x 个结果。在缓存中为您的查询字段创建一个条目。这可能看起来像这样:
{
"Query": {
"cursor": "cursor1",
"entry": { "comments": [{ ... }, { ... }] }
}
}
// normalised
{
"Query": {
"cursor": "cursor1",
"entry": Ref("Entry:1"),
}
"Entry:1": {
comments: [Ref("Comment:1"), Ref("Comment:2")],
},
"Comment:1": { ... },
"Comment:2": { ... }
}
- 用户点击加载更多,您的查询被再次获取,但带有光标值。游标告诉 API 它应该从哪个条目开始 returning 值。在我们的示例中
Comment
之后,id2
. - 查询结果进来,你使用
updateQuery
函数手动更新缓存中的查询结果。这里的想法是我们要将旧结果(列表)与新结果列表合并。我们已经获取了 2 条评论,现在我们要添加这两条新评论。您必须 return 一个结果,该结果是两个查询的组合结果。为此,我们需要更新光标值(以便我们可以再次单击“加载更多”并连接评论列表。该值已写入缓存,我们的规范化缓存现在如下所示:
{
"Query": {
"cursor": "cursor2",
"entry": { "comments": [{ ... }, { ... }, { ... }, { ... }] }
}
}
// normalised
{
"Query": {
"cursor": "cursor2",
"entry": Ref("Entry:1"),
}
"Entry:1": {
comments: [Ref("Comment:1"), Ref("Comment:2"), Ref("Comment:3"), Ref("Comment:4")],
},
"Comment:1": { ... },
"Comment:2": { ... },
"Comment:3": { ... },
"Comment:4": { ... }
}
- 由于您的组件订阅了查询,它将使用缓存中的新查询结果重新呈现!数据显示在 UI 中,因为我们合并了查询,以便组件获取新数据,就像结果首先包含所有四个评论一样。
这取决于你如何处理偏移量。我将尝试为您简化示例。
这是我使用成功的简化组件:
const PlayerStats = () => {
const { data, loading, fetchMore } = useQuery(CUMULATIVE_STATS, {
variables: sortVars,
})
const players = data.GetCumulativeStats
const loadMore = () => {
fetchMore({
variables: { offset: players.length },
updateQuery: (prevResult, { fetchMoreResult }) => {
if (!fetchMoreResult) return prevResult
return {
...prevResult,
GetCumulativeStats: [
...prevResult.GetCumulativeStats,
...fetchMoreResult.GetCumulativeStats,
],
}
},
})
}
我的 CUMULATIVE_STATS
默认查询 returns 50 行。我将该结果数组的长度作为 offset
传递给我的 fetchMore
查询。所以当我用fetchMore
执行CUMULATIVE_STATS
时,查询的变量都是sortVars
和offset
.
我在后端的解析器处理 offset
,因此如果它是,例如,50,它会忽略查询的前 50 个结果,returns 从那里开始的下一个 50(即第 51-100 行)。
然后在 updateQuery
中我有两个对象可用:prevResult
和 fetchMoreResult
。在这一点上,我只是使用扩展运算符将它们组合起来。如果没有新的结果被 returned,我 return 以前的结果。
当我再取一次的时候,players.length
的结果就变成了100,而不是50。这就是我的新偏移量,下次调用fetchMore
的时候会查询到新的数据。