Skip to content

Conversation

@teastudiopl
Copy link

What?

This PR adds a new method refreshCart to the E-commerce plugin.

Why?

Currently, the standard addItem method enforces uniqueness validation for products in the cart. This conflicts with certain use cases where the same product should be added as a new line item.

By exposing refreshCart, developers can manually refresh the cart state after directly modifying cart items, ensuring the UI stays in sync without being blocked by addItem’s uniqueness validation.

This addresses the feature request described in #14765
and the related discussion #14764
.

How?

Added refreshCart method to the E-commerce context.

This allows programmatic updates to the cart state without triggering the uniqueness validation of addItem.

The method can be called after direct modifications to the cart (e.g., via fetch requests or custom logic).

Fixes

Fixes #14765

@teastudiopl teastudiopl changed the title #14765 - Ecommerce Plugin - Expose manual refreshCart in useCart #14765 - feat Ecommerce Plugin - Expose manual refreshCart in useCart Nov 30, 2025
@teastudiopl teastudiopl changed the title #14765 - feat Ecommerce Plugin - Expose manual refreshCart in useCart feat(plugin-ecommerce): expose manual refreshCart in useCart (#14765) Nov 30, 2025
@teastudiopl teastudiopl changed the title feat(plugin-ecommerce): expose manual refreshCart in useCart (#14765) feat(plugin-ecommerce): expose method refreshCart in useCart (#14765) Nov 30, 2025
@DanRibbens DanRibbens requested a review from paulpopus December 4, 2025 16:10
) => Promise<unknown>
paymentMethods: PaymentAdapterClient[]
/**
* Refresh the cart.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A little light on detail for what I would want to see from this jsdoc

@paulpopus
Copy link
Contributor

While I'm not opposed to adding a refreshCart method, I want to understand more about the reasoning and the exact issue with the existing reducer's logic.

It's true that we merge the same product ID/variant ID together and I would be open to explore either making that part customisable or providing a config option to not merge the items but I need some more information around this.

refreshCart might still be needed for say maintaining cross-platform or cross-tab sync so I'm not blocking this PR but maybe there's a better way to solve your actual issue

@teastudiopl
Copy link
Author

teastudiopl commented Dec 4, 2025

I added refreshCart() because when adding items to the cart directly through a PATCH request (instead of using the built-in addItem helper), the local cart state was not automatically updated.

The addItem() method internally triggers Payload’s cart refresh logic, so the frontend always gets the newest cart.
But when I manually send a request like:

await fetch(/api/carts/${cart.id}, { method: "PATCH", ... })

Payload doesn’t automatically re-fetch the updated cart data.
This means the UI continued showing the old cart state until a full page reload or another action triggered a refresh by another addItem().

By explicitly calling:

await refreshCart()

I ensure that after the custom PATCH request succeeds, the cart in the frontend is immediately synchronized with the server.

my use case (not finished yet)::

  const addToCart = useCallback(
    async (e: React.FormEvent<HTMLButtonElement>) => {
      e.preventDefault()
 
      const newItem = {
        product: product.id,
        variant: selectedVariant?.id ?? undefined,

        itemData: JSON.stringify({
          ...
        }),
      }

      if (!cart?.id) {
        await addItem(newItem, 1)
        return
      }

      const existingItems = cart.items ?? []

      const newItems = [...existingItems, { ...newItem, quantity: 1 }]

      await fetch(`/api/carts/${cart.id}`, {
        method: 'PATCH',
        credentials: 'include',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ items: newItems }),
      }).then((response) => {
        if (response.ok) {
          toast.success(t('addedToCart'))
        }
      })

      await refreshCart()
    },
    [addItem, product, selectedLicense, selectedAddons, domain, totalPrice, selectedVariant],
  )

I expect each added product to be displayed as a separate item in the cart, because it includes specific settings defined by the user at the moment it is added to the cart.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ecommerce Plugin - Expose manual refreshCart and updateCart in useCart

3 participants