skip to Main Content

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;
          },
        },
      },
    },
  },
});

2

Answers


  1. Chosen as BEST ANSWER

    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;
              },
            },
          },
        },
      },
    });
    

  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search