Skip to main content
Use this hook when you need to track ongoing checkout actions and show loading states in your UI. It’s useful for disabling buttons, showing spinners, or preventing user interactions while the checkout is processing.

Import

import { usePendingActions } from '@ollie-shop/react';

Return Value

PropertyTypeDescription
hasPendingActionsbooleanWhether there are any checkout actions currently in progress
pendingActionsActionType[]Array of action types currently being processed
addActionNameForLoading(action: ActionType, isEarly?: boolean) => voidAdds an action to the pending list
removeActionNameForLoading(action: ActionType) => voidRemoves an action from the pending list

ActionType Values

The pendingActions array can contain any of these action types:
ActionTypeDescription
ADD_ITEMSAdding items to cart
REMOVE_ITEMSRemoving items from cart
UPDATE_ITEMS_QUANTITYUpdating item quantities
UPDATE_COUPONSApplying or removing coupons
UPDATE_SHIPPING_PACKAGESSelecting shipping options
UPDATE_SHIPPING_ADDRESSESUpdating shipping address
UPDATE_PAYMENT_METHODSSelecting payment methods
UPDATE_GIFT_CARDSApplying gift cards
UPDATE_CUSTOMER_DETAILSUpdating customer information
UPDATE_CUSTOMER_PREFERENCESUpdating customer preferences

Usage

const { hasPendingActions, pendingActions } = usePendingActions();

// Simple check for any pending action
if (hasPendingActions) {
  // Show loading state
}

// Check for specific actions
const isUpdatingCart = pendingActions.includes('UPDATE_ITEMS_QUANTITY');

Example

A totalizer component that shows a loading skeleton while cart-related actions are processing.
import { usePendingActions, useCheckoutSession } from '@ollie-shop/react';
import type { ActionType } from '@ollie-shop/react';
import styles from './styles.module.css';

const TOTALIZER_ACTIONS: ActionType[] = [
  'UPDATE_ITEMS_QUANTITY',
  'REMOVE_ITEMS',
  'UPDATE_SHIPPING_PACKAGES',
  'UPDATE_PAYMENT_METHODS',
];

function isUpdatingTotalizers(pendingActions: ActionType[]): boolean {
  return pendingActions.some((action) =>
    TOTALIZER_ACTIONS.includes(action)
  );
}

function formatCurrency(value: number, currency: string, locale: string): string {
  return new Intl.NumberFormat(locale, {
    style: 'currency',
    currency,
  }).format(value / 100);
}

function CheckoutTotalizer() {
  const { session } = useCheckoutSession();
  const { pendingActions } = usePendingActions();

  const { totals, locale } = session;
  const isUpdating = isUpdatingTotalizers(pendingActions);

  const formatPrice = (price: number) =>
    formatCurrency(price, locale.currency, locale.locale);

  return (
    <div className={styles.container}>
      <div className={styles.row}>
        <span>Subtotal</span>
        {isUpdating ? (
          <span className={styles.skeleton} />
        ) : (
          <span>{formatPrice(totals.subtotal)}</span>
        )}
      </div>
      <div className={styles.row}>
        <span>Shipping</span>
        {isUpdating ? (
          <span className={styles.skeleton} />
        ) : (
          <span>{formatPrice(totals.shipping)}</span>
        )}
      </div>
      <div className={`${styles.row} ${styles.total}`}>
        <span>Total</span>
        {isUpdating ? (
          <span className={styles.skeletonLarge} />
        ) : (
          <span>{formatPrice(totals.total)}</span>
        )}
      </div>
    </div>
  );
}

Notes

  • The addActionNameForLoading and removeActionNameForLoading functions are automatically called by useCheckoutAction when actions start and complete
  • Use hasPendingActions for simple loading states, or filter pendingActions for more granular control
  • Related: useCheckoutSession