Update selected delivery options
This guide shows you how to use a cart handler to update selected delivery options, such as standard or expedited delivery.
Anchor to RequirementsRequirements
- You've completed the quickstart guide.
- You've set up a cart handler.
Anchor to Step 1: Read selected and available delivery groupsStep 1: Read selected and available delivery groups
Carts return an empty array for available delivery groups by default. To get a list of delivery groups, the cart must be associated with a customer access token by updating the buyer identity when a customer is logged in.
Update the cart query fragment to return selected and available delivery options.
File
server.js
const cart = createCartHandler({
storefront,
getCartId: cartGetIdDefault(request.headers),
setCartId: cartSetIdDefault(),
cartQueryFragment: CART_QUERY_FRAGMENT,
});
const CART_QUERY_FRAGMENT = `#graphql
fragment CartApiQuery on Cart {
id
deliveryGroups(first: 1) {
nodes {
id
deliveryOptions {
handle
title
code
estimatedCost {
amount
currencyCode
}
}
selectedDeliveryOption {
handle
}
}
}
}
`;
const cart = createCartHandler({
storefront,
getCartId: cartGetIdDefault(request.headers),
setCartId: cartSetIdDefault(),
cartQueryFragment: CART_QUERY_FRAGMENT,
});
const CART_QUERY_FRAGMENT = `#graphql
fragment CartApiQuery on Cart {
id
deliveryGroups(first: 1) {
nodes {
id
deliveryOptions {
handle
title
code
estimatedCost {
amount
currencyCode
}
}
selectedDeliveryOption {
handle
}
}
}
}
`;
Anchor to Step 2: Create a select delivery option formStep 2: Create a select delivery option form
Use React Router's useFetcher
hook to create a cart note form. The hook submits a form request to the /cart
route's action when users choose a delivery option. You can use this component anywhere in the app.
When you use fetcher.submit
, make sure there's a data key with the name CartForm.INPUT_NAME
. The key value must be a JSON stringified object with action
and inputs
defined.
File
/app/components/SelectDeliveryGroup.jsx
import {CartForm} from '@shopify/hydrogen';
function SelectDeliveryGroup({deliveryGroups}) {
const fetcher = useFetcher();
const group = deliveryGroups?.nodes[0];
const deliveryOptions = group.deliveryOptions;
const selectedHandle = group.selectedDeliveryOption?.handle;
return (
<div>
{deliveryOptions.map((option) => {
return (
<div key={option.handle}>
<input
checked={selectedHandle === option.handle}
type="radio"
name="delivery"
value={option.handle}
id={option.handle}
onChange={(event) = /> {
fetcher.submit(
{
[CartForm.INPUT_NAME]: JSON.stringify({
action: CartForm.ACTIONS.SelectedDeliveryOptionsUpdate,
inputs: {
selectedDeliveryOptions: [{
deliveryGroupId: group.id,
deliveryOptionHandle: event.target.value,
}],
},
}),
},
{method: 'POST', action: '/cart'}
)
}}
/>
<label htmlFor={option.handle}>{option.title}</label>
</div>
)
})}
</div>
);
}
import {CartForm, type CartActionInput} from '@shopify/hydrogen';
import type {Cart} from '@shopify/hydrogen/storefront-api-types';
function SelectDeliveryGroup({
deliveryGroups
}: {
deliveryGroups: Cart['deliveryGroups'];
}) {
const fetcher = useFetcher();
const group = deliveryGroups?.nodes[0];
const deliveryOptions = group.deliveryOptions;
const selectedHandle = group.selectedDeliveryOption?.handle;
return (
<div>
{deliveryOptions.map((option) => {
return (
<div key={option.handle}>
<input
checked={selectedHandle === option.handle}
type="radio"
name="delivery"
value={option.handle}
id={option.handle}
onChange={(event) = /> {
fetcher.submit(
{
[CartForm.INPUT_NAME]: JSON.stringify({
action: CartForm.ACTIONS.SelectedDeliveryOptionsUpdate,
inputs: {
selectedDeliveryOptions: [{
deliveryGroupId: group.id,
deliveryOptionHandle: event.target.value,
}],
},
}),
},
{method: 'POST', action: '/cart'}
)
}}
/>
<label htmlFor={option.handle}>{option.title}</label>
</div>
)
})}
</div>
);
}
Anchor to Step 3: Handle the selected delivery option form requestStep 3: Handle the selected delivery option form request
Handle the selected delivery option form request in an action
. Use the cart
, created from createCartHandler
, to handle cart mutation requests to the Storefront API.
File
/app/routes/cart.jsx
import {CartForm} from '@shopify/hydrogen';
import invariant from 'tiny-invariant';
export async function action({request, context}) {
const {cart} = context;
const formData = await request.formData();
const {action, inputs} = CartForm.getFormInput(formData);
let result;
switch(action) {
case CartForm.ACTIONS.SelectedDeliveryOptionsUpdate:
result = await cart.updateSelectedDeliveryOption(inputs.selectedDeliveryOptions);
break;
default:
invariant(false, `${action} cart action is not defined`);
}
// The Cart ID might change after each mutation, so update it each time.
const headers = cart.setCartId(result.cart.id);
return json(
result,
{status: 200, headers},
);
}
import {
type CartQueryData,
CartForm,
} from '@shopify/hydrogen';
import invariant from 'tiny-invariant';
export async function action({request, context}: ActionArgs) {
const {cart} = context;
const formData = await request.formData();
const {action, inputs} = CartForm.getFormInput(formData);
let result: CartQueryData;
switch(action) {
case CartForm.ACTIONS.SelectedDeliveryOptionsUpdate:
result = await cart.updateSelectedDeliveryOption(inputs.selectedDeliveryOptions);
break;
default:
invariant(false, `${action} cart action is not defined`);
}
// The Cart ID might change after each mutation, so update it each time.
const headers = cart.setCartId(result.cart.id);
return json(
result,
{status: 200, headers},
);
}