简体   繁体   English

Apollo GraphQL updateQuery to typePolicy

[英]Apollo GraphQL updateQuery to typePolicy

I am beating my head against a wall.我正在用头撞墙。 I have updated to Apollo 3, and cannot figure out how to migrate an updateQuery to a typePolicy .我已经更新到 Apollo 3,但不知道如何将updateQuery迁移到typePolicy I am doing basic continuation based pagination, and this is how I used to merged the results of fetchMore :我正在做基本的基于延续的分页,这就是我过去合并fetchMore结果的方式:

await fetchMore({
  query: MessagesByThreadIDQuery,
  variables: {
    threadId: threadId,
    limit: Configuration.MessagePageSize,
    continuation: token
  },
  updateQuery: (prev, curr) => {
    // Extract our updated message page.
    const last = prev.messagesByThreadId.messages ?? []
    const next = curr.fetchMoreResult?.messagesByThreadId.messages ?? []

    return {
      messagesByThreadId: {
        __typename: 'MessagesContinuation',
        messages: [...last, ...next],
        continuation: curr.fetchMoreResult?.messagesByThreadId.continuation
      }
    }
  }

I have made an attempt to write the merge typePolicy myself, but it just continually loads and throws errors about duplicate identifiers in the Apollo cache.我尝试自己编写merge typePolicy ,但它只是不断加载并抛出有关 Apollo 缓存中重复标识符的错误。 Here is what my typePolicy looks like for my query.这是我的查询的typePolicy的样子。

  typePolicies: {
    Query: {
      fields: {
        messagesByThreadId: {
          keyArgs: false,
          merge: (existing, incoming, args): IMessagesContinuation => {
            const typedExisting: IMessagesContinuation | undefined = existing
            const typedIncoming: IMessagesContinuation | undefined = incoming
            const existingMessages = (typedExisting?.messages ?? [])
            const incomingMessages = (typedIncoming?.messages ?? [])

            const result = existing ? {
              __typename: 'MessageContinuation',
              messages: [...existingMessages, ...incomingMessages],
              continuation: typedIncoming?.continuation
            } : incoming


            return result
          }
        }
      }
    }
  }

So I was able to solve my use-case.所以我能够解决我的用例。 It seems way harder than it really needs to be.这似乎比实际需要的要难得多。 I essentially have to attempt to locate existing items matching the incoming and overwrite them, as well as add any new items that don't yet exist in the cache.我基本上必须尝试找到与传入匹配的现有项目并覆盖它们,以及添加缓存中尚不存在的任何新项目。

I also have to only apply this logic if a continuation token was provided, because if it's null or undefined, I should just use the incoming value because that indicates that we are doing an initial load.如果提供了延续令牌,我还必须仅应用此逻辑,因为如果它是 null 或未定义,我应该只使用传入值,因为这表明我们正在进行初始加载。

My document is shaped like this:我的文档是这样的:

{
  "items": [{ id: string, ...others }],
  "continuation": "some_token_value"
}

I created a generic type policy that I can use for all my documents that have a similar shape.我创建了一个通用类型策略,我可以将其用于我所有具有相似形状的文档。 It allows me to specify the name of the items property, what the key args are that I want to cache on, and the name of the graphql type.它允许我指定项目属性的名称、我要缓存的关键参数是什么以及 graphql 类型的名称。

export function ContinuationPolicy(keyArgs: Array<string>, itemPropertyKey: string, typeName: string) {
  return {
    keyArgs,
    merge(existing: any, incoming: any, args: any) {
      if (!!existing && !!args.args?.continuation) {
        const existingItems = (existing ? existing[itemPropertyKey] : [])
        const incomingItems = (incoming ? incoming[itemPropertyKey] : [])
        let items: Array<any> = [...existingItems]

        for (let i = 0; i < incomingItems.length; i++) {
          const current = incomingItems[i] as any
          const found = items.findIndex(m => m.__ref === current.__ref)

          if (found > -1) {
            items[found] === current
          } else {
            items = [...items, current]
          }
        }

        // This new data is a continuation of the last data.
        return {
          __typename: typeName,
          [itemPropertyKey]: items,
          continuation: incoming.continuation
        }
      } else {
        // When we have no existing data in the cache, we'll just use the incoming data.
        return incoming
      }
    }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM