Home > other >  Pagination doesn't work. I need to update from updateQuery to field policies
Pagination doesn't work. I need to update from updateQuery to field policies

Time:02-04

I need to figure out how to update the onFetchMore method. I have a page, on this page I see 10 elements and, when I click on the "Show more" button, I have to add another 10 elements, etc. So I must add to the existing ones of the others. When I click, the warning pops up in the console (The updateQuery callback for fetchMore is deprecated, and will be removed in the next major version of Apollo Client.)

 const { loading, error, data, networkStatus, fetchMore } = useQuery(sezioneByUuid, {
    variables: { slug: slug || sezione, limit: 10 },
    errorPolicy: 'all',
    fetchPolicy: 'network-only',
    partialRefetch: true,
    notifyOnNetworkStatusChange: true,
    skip: false,
  });

  const onFetchMore = useCallback(() => {
    const {
      page: {
        apertura,
        block: {
          set: {
            pagedItems: { items },
          },
        },
      },
    } = data;
    fetchMore({
      variables: {
        limit: 10,
        exclude: [apertura.set.first.uuid].concat(
          items.map((articolo) => {
            const { uuid } = articolo;
            return uuid;
          }),
        ),
      },
      updateQuery: (prev, { fetchMoreResult }) => {
        if (!fetchMoreResult) return prev;
        // prev
        const {
          mktg,
          page: {
            __typename: pageTypeName,
            slug,
            uuid,
            section,
            seo,
            apertura,
            block: {
              page,
              __typename: blockTypeName,
              uuid: blockUuid,
              set: {
                __typename: setTypeName,
                uuid: setUuid,
                pagedItems: { uuid: pagedItemsUuid, __typename: pagedItemsTypeName, items: oldItems },
              },
            },
          },
        } = prev;
        // fetch more contents
        const { items: newItems, hasNext, excluded } = fetchMoreResult.page.block.set.pagedItems;

        return {
          page: {
            uuid,
            __typename: pageTypeName,
            slug,
            block: {
              page,
              uuid: blockUuid,
              __typename: blockTypeName,
              set: {
                uuid: setUuid,
                __typename: setTypeName,
                pagedItems: {
                  uuid: pagedItemsUuid,
                  __typename: pagedItemsTypeName,
                  items: [...items, ...newItems],
                  hasNext,
                  excluded,
                },
              },
            },
            section,
            seo,
            apertura,
          },
          mktg,
          social: prev.social,
        };
      },
    });
  }, [data, fetchMore]);

I'm trying to edit with the field policy, then eliminating updateQuery() but I get this message (Cache data may be lost when replacing the set field of a Block object.) Can anyone help me?

const cache = new InMemoryCache({
  typePolicies: {
    Query: {
      fields: {
        sezione: {
          //keyFields: ["sezione"],
          // Don't cache separate results based on
          // any of this field's arguments.
          keyArgs: false,
          // Concatenate the incoming list items with
          // the existing list items.
          merge(existing, incoming) {
            if (!incoming) return existing;
            if (!existing) return incoming; // existing will be empty the first time

            const { items, ...rest } = incoming;

            let result = rest;
            result.items = [...existing.items, ...items]; // Merge existing items with the items from incoming

            return result;
          },
        },
      },
    },
  },
});

CodePudding user response:

Add a dataIdFromObject function so that Apollo knows to key against your id field uuid on all objects, since this is different to the default id or _id that apollo looks for.

const cache = new InMemoryCache({
  dataIdFromObject(responseObject) {
    return `${responseObject.__typename}:${responseObject.uuid}`
  },
  typePolicies: {
    Query: {
      fields: {
        sezione: {
          //keyFields: ["sezione"],
          // Don't cache separate results based on
          // any of this field's arguments.
          keyArgs: false,
          // Concatenate the incoming list items with
          // the existing list items.
          merge(existing, incoming) {
            if (!incoming) return existing;
            if (!existing) return incoming; // existing will be empty the first time

            const { items, ...rest } = incoming;

            let result = rest;
            result.items = [...existing.items, ...items]; // Merge existing items with the items from incoming

            return result;
          },
        },
      },
    },
  },
});

Note this assumes every object in your GQL schema has a UUID. If there's differences between types you need to do it the other way.

CodePudding user response:

In my management I added the dataIdFromObject() function but that warning keeps coming out.

const dataIdFromObject = (object) => {
  // eslint-disable-next-line no-underscore-dangle
  const typename = object.__typename;
  switch (typename) {
    case 'Block':
      return `${typename.toLowerCase()}:${object.page}-${object.uuid}`;
    case 'ContentSet':
      return defaultDataIdFromObject(object);
    case 'Image':
      return `${typename.toLowerCase()}:${object.src}`;
    case 'Page':
      return `${typename.toLowerCase()}:${object.slug}`;
    case 'PagedContent':
      return defaultDataIdFromObject(object);
    case 'Leaf':
      return defaultDataIdFromObject(object);
    default:
      if (object.uuid) {
        return `${typename.toLowerCase()}:${object.uuid}`;
      }
      return defaultDataIdFromObject(object); // fall back to default handling
  }
  // }
};

const cache = new InMemoryCache({
  dataIdFromObject,

  typePolicies: {
    Query: {
      fields: {
        sezione: {
          // Don't cache separate results based on
          // any of this field's arguments.
          keyArgs: false,
          // Concatenate the incoming list items with
          // the existing list items.
          merge(existing, incoming) {
            if (!incoming) return existing;
            if (!existing) return incoming; // existing will be empty the first time

            const { items, ...rest } = incoming;

            let result = rest;
            result.items = [...existing.items, ...items]; // Merge existing items with the items from incoming

            return result;
          },
        },
      },
    },
  },
});
  • Related