Skip to content

feat: add cart refresh API - #3967

Draft
andguy95 wants to merge 2 commits into
previewfrom
an-cart-refresh-util
Draft

feat: add cart refresh API#3967
andguy95 wants to merge 2 commits into
previewfrom
an-cart-refresh-util

Conversation

@andguy95

@andguy95 andguy95 commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

TL;DR: Gives developers a way to refresh the client-side cart after something outside Hydrogen changes it — like a third-party app, a direct API call, or a webhook.

Today, if the cart gets changed outside of Hydrogen's built-in cart forms, the client has no idea until the next full page load. refresh() fixes that.

Before

After an out-of-band cart change, the client-side cart is stale. No way to pull the latest state without a page reload.

After

import { useCartActions } from "~/lib/cart";

function CustomCartEditor() {
  const { refresh } = useCartActions();

  async function save() {
    await saveCustomCartData();
    refresh();
  }
}

refresh() is fire-and-forget. You can watch state.revalidating for progress and state.errors.network for failures. Existing cart data is preserved if the refresh fails.

What this changes

  • Adds CartStore.refresh() to the core cart store. It waits for any in-flight optimistic mutations to finish, fetches the cart from the configured endpoint, and merges the response — including custom fragment fields like metafields.
  • Adds a useCartActions() hook for React and Vue. Both return { refresh } and throw a clear error if used outside <CartProvider>.
  • Exports useCartActions and the CartActions type from @shopify/hydrogen/react and @shopify/hydrogen/vue.
  • Includes useCartActions in the createCartComponents() factory so typed cart setups get it automatically.
  • Updates the hydrogen-cart-ui skill docs and React/Vue references with usage guidance.
  • Adds a dependency map entry for the cart store API surface.

Developer impact

Includes a minor changeset for @shopify/hydrogen. New exports only, nothing breaks.

Don't call refresh() after normal Hydrogen cart form submissions — those already sync the store automatically.

Out of scope

  • refresh() returns void, not a Promise. This is intentional — a newer refresh() call cancels the previous one, so there's no clear value a Promise would resolve to. Watch state.revalidating instead.
  • Refresh errors and mutation errors look the same in state.errors.network. Fine for now; a separate error field could be added later without breaking anything.

Risk

Low. The refresh reuses the store's existing revalidation pipeline — same concurrency guards, same abort handling, same staleness checks. No new state machine paths. Calling refresh() during an in-flight mutation is safe; it queues up and runs after.

@andguy95
andguy95 marked this pull request as ready for review August 21, 2026 21:39
@andguy95
andguy95 requested a review from a team as a code owner August 21, 2026 21:39
refresh() previously no-oped when the store had no cart id. That left a gap
for out-of-band mutations that create a cart server-side (e.g. cartCreate
writing the cart cookie): the new cart would never reach the client store.

Fall back to a full load in that case so refresh discovers the freshly
created cart, while keeping same-cart revalidation for carts that already
exist. Updates the changeset, cart-ui skill, and tests accordingly.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant