Skip to main content

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

Was this page helpful?