Apollo GraphQL updateQuery to typePolicy

Sep 01 2020

ฉันเอาหัวโขกกำแพง ฉันได้อัปเดตเป็น Apollo 3 แล้วและไม่สามารถหาวิธีย้ายไฟล์updateQueryไปยังไฟล์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 cache นี่คือ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

ดังนั้นฉันจึงสามารถแก้ปัญหาการใช้งานของฉันได้ ดูเหมือนว่าจะยากกว่าที่จำเป็นจริงๆ โดยพื้นฐานแล้วฉันต้องพยายามค้นหารายการที่มีอยู่ที่ตรงกับขาเข้าและเขียนทับรวมถึงเพิ่มรายการใหม่ ๆ ที่ยังไม่มีในแคช

ฉันต้องใช้ตรรกะนี้ก็ต่อเมื่อมีการระบุโทเค็นความต่อเนื่องเพราะถ้าเป็นโมฆะหรือไม่ได้กำหนดฉันควรใช้ค่าขาเข้าเพราะนั่นแสดงว่าเรากำลังทำการโหลดครั้งแรก

เอกสารของฉันมีรูปร่างดังนี้:

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

ฉันสร้างนโยบายประเภททั่วไปที่สามารถใช้กับเอกสารทั้งหมดของฉันที่มีรูปร่างคล้ายกัน ช่วยให้ฉันระบุชื่อของคุณสมบัติรายการสิ่งที่คีย์ args ที่ฉันต้องการแคชและชื่อของประเภท 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
      }
    }
  }
}