Re:

Hydrogen | Open drawer when AddToCartButton clicked

L521
Shopify Partner
3 0 2

I am working with the Hydrogen demo store , and wondering if there is a simple way to trigger the cart drawer to open when the Add to cart button is clicked.

 

https://stackblitz.com/github/Shopify/hydrogen/tree/dist/templates/demo-store-ts

 

Thank you,

 

Replies 3 (3)

KlemShad
Visitor
2 0 0

I'm looking for this very thing. Let me know if you have found a solution yet.

SJCapaldi
Shopify Partner
4 0 0

You can implement it like so...

Added an optional onClick to the AddToCartButton component:

 

 

/** Optional onclick prop */
onClick?(event: React.MouseEvent<HTMLButtonElement>): void;

 


Then in the product form/wherever your Add to Cart button is called, I've passed in openCart:

 

<>
<form>
...
<div className="grid items-stretch gap-4">
   <AddToCartButton
     variantId={selectedVariant?.id}
     quantity={1}
     accessibleAddingToCartLabel="Adding item to your cart"
     disabled={isOutOfStock}
     type="button"
     onClick={openCart}
   >
    <span
      className={`${
      isOutOfStock ? 'btn btn-secondary' : 'btn btn-primary'
      } w-full`}
    >
      {isOutOfStock ? (
       <span
        className="btn-padding disabled:cursor-not-allowed"
        disabled
       >
         Sold out
        </span>
              ) : (
                <span className="btn-padding">Add to bag</span>
              )}
            </span>
          </AddToCartButton>
        </div>
      </form>
      <CartDrawer isOpen={isCartOpen} onClose={closeCart} />
   </>

 

 

This will open the cart drawer, add the item to the cart and display it.

Might be a cleaner way of doing this but this is definitely the quickest.

Creative Frontend Engineer specialising in Headless Commerce
jackmcpickle
Shopify Partner
4 0 0

Found a better way.

 

using useOutletContext see docs - https://reactrouter.com/en/6.11.0/hooks/use-outlet-context

 

I set the cart drawer state in the root.tsx then called useOutletContext in my AddToCartButton component with a useEffect to detect with the formFetcher had been successful. 

 

 

 

// root.tsx

const [isCartDrawerOpen, setCartDrawerOpen] = useState(false);
// then later

<Outlet
  context={{
    isCartOpen: isCartDrawerOpen,
    setCartDrawerOpen,
  }}
/>

 

then 

 

//
function AddToCartButton({
    children,
    lines,
    className = '',
    variant = 'primary',
    width = 'full',
    disabled,
    analytics,
    ...props
}: AddToCartButtonProps) {
    const [root] = useMatches();
    const selectedLocale = root?.data?.selectedLocale;
    const fetcher = useFetcher();
    const fetcherIsNotIdle = fetcher.state !== 'idle';

    const { setCartDrawerOpen } = useOutletContext<OutletContext>();

    useEffect(() => {
        setCartDrawerOpen(Boolean(fetcher?.data?.success));
    }, [fetcher?.data?.success]);

    return (
        <fetcher.Form
            className="w-full"
            action="/cart"
            method="POST"
        >
// etc...

 

 

I also added in my cart action the success key. 

 

// routes/cart.tsx
// inside action()

  return json(
        {
            cart,
            success: errors?.length === 0,
            errors,
            analytics: {
                cartId,
            },
        },
        { status, headers },
    );