Adding multiple to cart
Our Storeapi supports a mutation addMultipleToCart
that takes a cart ID and a list
of products. It will add all of the products to cart if it can, and will return
errors for any that failed.
Whilst the mutation can be used directly, the Flight framework comes with a hook that does some of the work for you.
useMultipleAddToCart
Example usage:
const [addMultipleToCart, { loading, called, data, error, failedItems }] =
useAddMultipleToCart(
items,
{ cartQuery, addMultipleToCartMutation },
{ onCompleted, onError, onPartialFailure }
);
This hook takes the follow arguments:
items: AddMultipleProduct[],
queries: AddMultipleToCartQueries,
callbacks?: UseAddMultipleToCartOption
The type definitions for the arguments are as follows:
interface AddMultipleProduct extends Product, AddMultipleToCartInput {}
type AddMultipleToCartMutationResponse = FetchResult<{
addMultipleToCart: CartMutation;
}>;
interface AddMultipleToCartQueries {
addMultipleToCartMutation: DocumentNode;
cartQuery: DocumentNode;
}
interface UseAddMultipleToCartOptions {
onCompleted?(resp: AddMultipleToCartMutationResponse): any;
onError?(resp: AddMultipleToCartMutationResponse): any;
onPartialFailure?(resp: AddMultipleToCartMutationResponse): any;
}
items
The items argument should be an array of products with at minimum an articleNumber and quantity specified.
Each item may contain all normal Product
fields, as well as the fields on
AddMultipleToCartInput
(shown below).
type AddMultipleToCartInput {
articleNumber: String!
quantity: Int = null
comments: [InputComment] = null
configurationIds: [ID] = null
preOrderDate: DateTime = null
}
So, your items
array might look something like this:
const items = [
{
id: 145,
primaryRoute: {
path: "/random-products/with-1-level-attributes/kinky-ninja",
},
articleNumber: "1L1VZQ9180",
hasVariants: false,
quantity: 2,
},
{
id: 529,
primaryRoute: {
path: "/random-products/product-with-percent-discount",
},
articleNumber: "AD98D89DA",
hasVariants: false,
quantity: 10,
},
];
queries
The second argument, queries
, should be an object containing two keys:
addMultipleToCartMutation
This is the mutation. There is an example of this in Trend at
src/components/Cart/addMultipleToCart.gql
. This query should return the Cart
fragment, which is also used by the cartQuery. Doing this allows the cart to
automatically update after the mutation succeeds.
cartQuery
This should be the same query you use to query for your cart. This is needed in order to re-fetch your cart (to update quantities, price, etc) after the MultipleAddToCart mutation runs, in the case of a partial error.
By default in Trend, this query lives at src/components/Cart/queries/cartQuery.gql
callbacks
These are optional callbacks that can be used to add side-effects at different stages of the mutation.
onCompleted(response)
This will be called with the mutation response after the mutation succeeds (including when it succeeds with a partial failure).
onPartialFailure(response)
This will be called with the mutation response when some of the items are not able to be added to cart. The response will include the errors.
onError(response)
This will be called if the entire mutation fails, and no items could be added to cart. The response will include the error.
Return values
The return values are similar to Apollo Client's useMutation
, with some added
features.
The hook returns an tuple with the mutation as the first entry, and an object containing status flags and data as the second entry (the mutation result).
[
() => Promise<AddMultipleToCartMutationResponse>, // the mutation function
{
loading: boolean;
called: boolean;
error: boolean;
data: AddMultipleToCartMutationResponse;
failedItems: Map<AddMultipleProduct, FailedReason>;
}
]
Mutate function
This is identical to the mutation function returned by useMutation
. Calling
this function will fire off the mutation and return a Promise, which will
resolve with the response from the API.
Mutation result
The second entry is an object containing the result of the mutation.
loading
Whether or not the mutation is loading (in-flight).
called
Whether or not the mutation has been called at least once.
error
Whether or not the mutation has failed completely.
data
The full response from the API.
failedItems
If some items are added to the cart but others fail, failedItems
will include
those that failed. failedItems is a Map with each item
that failed as the key,
and the error code (string) as the value.
TIP: You can easily display the failed products by extracting them from the Map and converting the result to an array:
<div>
<h2>Failed items:</h2>
{[...failedItems.keys()].map((product) => (
<div key={product.id + product.quantity}>
{product.name} {product.articleNumber}
</div>
))}
</div>
You can also determine whether an item has failed inline like this:
function Products({ products }) {
const [mutate, { failedItems }] = useAddMultipleToCart(products, {
addMultipleToCartMutation,
cartQuery,
});
return products.map((product) => {
const failedProductCode = failedItems.get(product);
// will be undefined if the product did not fail
return (
<Product
product={product}
key={product.articleNumber}
failCode={failedProductCode}
/>
);
});
}
function Product({ product, failCode }) {
return (
<div>
{failCode && `Error code: ${failCode}`}
<h1 style={failCode ? { color: "red" } : { color: "blue" }}>
{product.name}
</h1>
</div>
);
}