Apollo GraphQL updateQuery to typePolicy

Sep 01 2020

나는 벽에 머리를 치고있다. 나는 아폴로 3로 업데이트 한과를 마이그레이션하는 방법을 알아낼 수 없습니다 updateQueryA를 typePolicy. 기본 연속 기반 페이지 매김을 수행하고 있으며 다음과 같은 결과를 병합하는 데 사용되었습니다 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
      }
    }
  }

merge typePolicy나 자신 을 작성하려고 시도 했지만 Apollo 캐시에 중복 식별자에 대한 오류가 계속로드되고 발생합니다. 여기 내 것입니다 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
          }
        }
      }
    }
  }

답변

DylanVester Sep 15 2020 at 14:21

그래서 제 사용 사례를 해결할 수있었습니다. 실제로 필요한 것보다 훨씬 더 어려워 보입니다. 기본적으로 들어오는 항목과 일치하는 기존 항목을 찾아 덮어 쓰고 캐시에 아직없는 새 항목을 추가해야합니다.

또한 연속 토큰이 제공된 경우에만이 논리를 적용해야합니다. null이거나 정의되지 않은 경우 초기로드를 수행하고 있음을 나타 내기 때문에 들어오는 값을 사용해야하기 때문입니다.

내 문서는 다음과 같은 모양입니다.

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

모양이 비슷한 모든 문서에 사용할 수있는 일반 유형 정책을 만들었습니다. 항목 속성의 이름, 캐시하려는 주요 인수 및 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
      }
    }
  }
}