Development Notes

Getting WooCommerce Cart to Work with React

11 Aug, 2026 , 4 min read

Building SnackStation started with a simple idea: use WooCommerce for the commerce backend and React for the customer-facing experience. The architecture made sense. WooCommerce would handle products, orders, and payments while React handled the storefront.

Then I got to the cart.

The Problem

WooCommerce works well when its frontend and backend live together. But once the frontend is completely separated from WordPress, some of the assumptions WooCommerce makes around sessions and cart state become a problem.

I spent weeks troubleshooting the cart and different WooCommerce add-ons. Getting products into the cart was one thing; keeping that cart consistent across requests from a separate React application was another.

Eventually, it became clear that I wasn't dealing with just a small bug. I was trying to make a traditional WooCommerce cart behave like an API-driven cart.

Enter CoCart

That's where CoCart came in.

CoCart gave me an API-first way of working with the WooCommerce cart, which was much closer to what my React frontend needed.

But adding CoCart wasn't the end of the problem. I still had to deal with product add-ons, coupons, checkout, delivery fees, payment gateways, and our own frontend requirements. So instead of relying entirely on the default cart flow, I built a custom REST API around WooCommerce.

$namespace = 'ss/v1';

register_rest_route($namespace, '/cart', [
    'methods' => 'GET',
    'callback' => [$this, 'get_cart']
]);

register_rest_route($namespace, '/cart/add', [
    'methods' => 'POST',
    'callback' => [$this, 'add_to_cart']
]);

This gave the React application a consistent API for interacting with the cart while WooCommerce remained responsible for the actual cart logic. 

The Session Problem

This was where things got interesting. REST requests don't necessarily go through WooCommerce's normal frontend lifecycle, so I had to explicitly make sure the cart and session were loaded.

I used wc_load_cart() and made sure a customer session existed before interacting with the cart.

private function ensure_cart() {
    if (function_exists('wc_load_cart') && is_null(WC()->cart)) {
        wc_load_cart();
    }

    if (WC()->session && !WC()->session->has_session()) {
        WC()->session->set_customer_session_cookie(true);
    }
}

That took care of loading the cart, but we also had to explicitly persist changes using WC()->cart->set_session() after cart operations. 

For example, after adding an item:

$key = WC()->cart->add_to_cart(
    $product_id,
    $quantity,
    0,
    [],
    $cart_item_data
);

WC()->cart->set_session();

The same pattern was used when updating quantities, removing items, clearing the cart, and applying coupons.

Keeping Add-ons Intact

SnackStation also had product add-ons, so the cart couldn't just store a product ID and quantity.

We passed the selected add-ons into the cart item data and then extracted them again when returning the cart to React.

That meant the frontend could receive a clean selectedAddons structure alongside each cart item instead of having to understand WooCommerce's internal cart object. 

Connecting CoCart to Checkout

Getting the cart working was one thing. Making checkout use the same cart session was another.

My checkout endpoint checked for my own x-ss-cart-key header and fell back to CoCart's x-cocart-session when necessary.

$cart_key = $request->get_header('x-ss-cart-key');

if (!$cart_key) {
    $cart_key = $request->get_header('x-cocart-session');
}

if ($cart_key !== '' && WC()->session) {
    WC()->session->set_customer_id($cart_key);
}

I then loaded WooCommerce's cart from that session before creating the order. This was the bridge that allowed our custom checkout flow to work with the cart session being managed through CoCart.

What I Learned

The biggest lesson from SnackStation wasn't simply "use CoCart."

It was understanding that headless WooCommerce isn't just about putting React in front of WordPress. WooCommerce has its own assumptions around sessions, carts, and its frontend lifecycle.

CoCart gave me the API-first cart layer I needed, but I still had to deliberately connect React, CoCart, WooCommerce sessions, and my custom API.

It took a frustrating few weeks to get there.

But once I stopped trying to force the traditional WooCommerce cart into a headless architecture and built around the way the systems actually worked, everything started making a lot more sense.

WooCommerce Headless WordPress React

Lanre Malumi

Lanre Malumi

https://lanremalumi.laravel.cloud

Most days, Lanre is somewhere between a Figma file and a Laravel project, trying to make both behave. Accessibility isn't an afterthought for him. "Works for everyone" is the actual bar, not a nice-to-have. When he's not working on something, he's probably watching a movie, overthinking a scene, or adding yet another title to his watchlist.

Comments

0 approved comments

Your email stays private. Comments appear after moderation.

No approved comments yet.

You might also like...