Saleor Shopping Cart Sometimes Wrong/Older Version - Using GraphQL and Next.js

160 views Asked by At

I am using Saleor shopping cart GraphQL, and actually Stepzen to merge it with a Strapi GraphQL. So all Saleor mutations and queries go through the Stepzen GraphQL.

I have followed Saleors tutorial here: https://learn.saleor.io/checkout/displaying-cart-content/

This works 90% of the time so generally the code should be OK, but I must be missing something because occasionally when adding to the cart the contents are different. The item is not added. In fact, it's possible the cart seen is an older version but am not sure. I could add to cart 4 times and it updates to the correct products and quantities each time, then the 5th time it shows the cart from the last time or even time before.

After a few seconds, if you refresh the page, the cart displays correct.

EDIT: I have just noticed, if you refresh the page several times, the cart sometimes changes, and a refresh changes back, then a refresh it changes to something else and just keeps changing on refreshes!

When the cart works, there is a little delay adding it, but when it doesn't work the cart page loads much faster, almost instantly. It's as if when it works it waits for Saleors response for the cart items list, but when it doesn't it doesn't wait for the response. Just a hunch.

This is my query code to get cart items from Saleor. It does work, 90% of the time.

const Cart = () => {
    const [token] = useCookies('["token"]')
    const { data, loading, error } = useCheckoutFetchByTokenQuery({
        variables: { checkoutToken: token.token },
        skip: !token.token,
    });
    const [CheckoutremoveProduct] = useCheckoutRemoveProductMutation();

    if (loading) return <div>Loading...</div>;
    if (error) return <div>Error</div>;
    if (!data || !data.saleorcheckout) return null;

    const products = data.saleorcheckout?.lines || [];
    
    return (
        <Layout title="Cart">
            .....
        </Layout>
    );
}

The actual saleorcheckout query:

query CheckoutFetchByToken($checkoutToken: saleorUUID!) {
  saleorcheckout(token: $checkoutToken) {
        id
        email
        lines {
            id
            quantity
            totalPrice {
                gross {
                    amount
                    currency
                }
            }
            variant {
                id
                product {
                    id
                    name
                    slug
                    thumbnail {
                        url
                        alt
                    }
                    cmsContent {
                        SaleorID
                        Title
                        Featured_image
                        {
                            data
                            {
                                attributes
                                {
                                    url
                                    width
                                    height
                                    alternativeText
                                }
                            }
                        }
                    }
                }
                pricing {
                    price {
                        gross {
                            amount
                            currency
                        }
                    }
                }
                name
            }
        }
        totalPrice {
            gross {
                amount
                currency
            }
        }
    }
}

Interestingly the saleorcheckoutLinesAdd mutation which adds lines to the cart returns with the correct products in the cart, after the new one is added, but on the cart page that uses saleorcheckout to fetch them returns a lower amount, until you refresh later.

The actual saleorcheckoutLinesAdd mutation:

mutation ProductAddVariantToCart($checkoutToken: saleorUUID!, $variantId: ID!) {
  saleorcheckoutLinesAdd(
    token: $checkoutToken
    lines: [{ quantity: 1, variantId: $variantId }]
  ) {
    checkout {
      id
      lines {
        id
        quantity
        variant {
          id
          name
          product {
            name
          }
        }
      }
    }
    errors {
      message
    }
  }
}

Thanks

UPDATE:

My first post above included this below, but it may be a red herring as I have added the variant ID in the query now, and dont get this error below anymore, but the problem above still exists.

Previously when it doesn't work the following error was in console:

react_devtools_backend.js:4026 Cache data may be lost when replacing the variant field of a saleorCheckoutLine object.

To address this problem (which is not a bug in Apollo Client), either ensure all objects of type saleorProductVariant have an ID or a custom merge function, or define a custom merge function for the saleorCheckoutLine.variant field, so InMemoryCache can safely merge these objects:

  existing: {"__typename":"saleorProductVariant","product":{"__ref":"saleorProduct:UHJvZHVjdDoxNjY="},"pricing":{"__typename":"saleorVariantPricingInfo","price":{"__typename":"saleorTaxedMoney","gross":{"__typename":"saleorMoney","amount":100,"currency":"USD"}}},"name":"UHJvZHVjdFZhcmlhbnQ6NDAy"}
  incoming: {"__typename":"saleorProductVariant","name":"UHJvZHVjdFZhcmlhbnQ6NDAy","product":{"__typename":"saleorProduct","name":"52-00 Base Plate"}}

I have looked this up, and the solution is to set typePolicies the ApolloClient to state to merge the new and old carts. BUT I cannot get this to work, if it is the solution. Online some examples of typePolicies and merge have console.log() outputs but mine are just not firing. So I am assuming I have not set the typePolicies up correct perhaps.

This is my typePolicies code, although I have tried many variations, and the fact lines is nested may be complicating it.

const client = new ApolloClient({
uri: "https://my-stepzen-graphql-url.com/__graphql", 
cache: new InMemoryCache({
    typePolicies: {
        Query: {
            fields: {
                    saleorcheckoutLinesAdd: {
                        lines: {
                            merge(existing, incoming, { mergeObjects }) {
                                console.log(existing)
                                console.log(incoming)
                                return mergeObjects(existing, incoming);
                            },
                        },
                    },
                },
            },
        },
    }),
})

I have tried many versions of the above typePolicies, but can never get console.log to fire, so assume I have fond the correct format.

0

There are 0 answers