Shopify / hydrogen

Hydrogen lets you build faster headless storefronts in less time, on Shopify.
https://hydrogen.shop
MIT License
1.37k stars 264 forks source link

useOptimisticCart doesn't add isOptimistic to cart and cart line item #2357

Open williamkhshea opened 2 months ago

williamkhshea commented 2 months ago

What is the location of your example repository?

No response

Which package or tool is having this issue?

Hydrogen

What version of that package or tool are you using?

2024.7.2

What version of Remix are you using?

2.10.3

Steps to Reproduce

When using useOptimisticCart(cart) by following the example

export function Cart({cart}) {
  const optimisticCart = useOptimisticCart(cart);

  if (!optimisticCart?.lines?.nodes?.length) return <p>Nothing in cart</p>;

  return optimisticCart.lines.nodes.map((line) => (
    <div key={line.id}>
      <Link to={`/products${line.merchandise.product.handle}`}>
        {line.merchandise.product.title}
      </Link>
    </div>
  ));
}

isOptimistic is not included in the cart and cart line items.

Screenshot 2024-07-24 at 1 55 28 AM

The issue is that useOptimisticCart is incorrectly assuming the cart object has lines.nodes, while it should be lines.edges[].node.

Screenshot 2024-07-24 at 2 06 35 AM

Expected Behavior

isOptimistic is returned in cart and cart line items.

Actual Behavior

isOptimistic is NOT returned in cart and cart line items.

blittle commented 2 months ago

At the moment useOptimisticCart only supports nodes, not edges. Is there a particular reason you need to be using edges?

juanpprieto commented 2 months ago

Yes, we don't support item edges just nodes

Here is isOptimistic using the default cart query.

Screenshot 2024-07-23 at 2 43 09 PM

Feel free to submit a PR though!

williamkhshea commented 2 months ago

@blittle No particular reason I have to use edges. It's more of a legacy issue.

I got it working now by switching to lines.nodes.

Here is my cart query for reference:

server.ts

/**
 * cartQueryFragment requirements:
 *
 * - Must be named `CartApiQuery`
 * - Only have access to the following query variables:
 *   - $cartId: ID!
 *   - $country: CountryCode
 *   - $language: LanguageCode
 *   - $numCartLines: Int
 *
 * https://shopify.dev/docs/custom-storefronts/hydrogen/cart/customize-cart-handler
 **/
const CART_QUERY_FRAGMENT = `#graphql
  fragment CartApiQuery on Cart {
    updatedAt
    id
    checkoutUrl
    totalQuantity
    buyerIdentity {
      countryCode
      customer {
        id
        email
        firstName
        lastName
        displayName
      }
      email
      phone
    }
    lines(first: $numCartLines) {
      nodes {
        id
        quantity
        attributes {
          key
          value
        }
        cost {
          totalAmount {
            amount
            currencyCode
          }
          amountPerQuantity {
            amount
            currencyCode
          }
          compareAtAmountPerQuantity {
            amount
            currencyCode
          }
        }
        sellingPlanAllocation {
          sellingPlan {
            name
          }
        }
        merchandise {
          ... on ProductVariant {
            id
            availableForSale
            barcode
            sku
            compareAtPrice {
              ...CartApiMoney
            }
            price {
              ...CartApiMoney
            }
            requiresShipping
            title
            image {
              ...CartApiImage
            }
            product {
              handle
              title
              id
              vendor
              productType
              onlineStoreUrl
            }
            selectedOptions {
              name
              value
            }
          }
        }
      }
    }
    cost {
      subtotalAmount {
        ...CartApiMoney
      }
      totalAmount {
        ...CartApiMoney
      }
      totalDutyAmount {
        ...CartApiMoney
      }
      totalTaxAmount {
        ...CartApiMoney
      }
    }
    note
    attributes {
      key
      value
    }
    discountCodes {
      applicable
      code
    }
  }
  fragment CartApiMoney on MoneyV2 {
    currencyCode
    amount
  }
  fragment CartApiImage on Image {
    id
    url
    altText
    width
    height
  }
`;