Skip to main content

usePaymentMethods()

Important

Billing regularly introduces new features and UI changes to Clerk's components. If you'd like to remain on a specific version of Clerk's components or SDK, you can follow the steps in the pinning documentation.

The usePaymentMethods() hook provides access to the payment methods associated with a user or Organization. It returns a paginated list of payment methods and includes methods for managing them.

Parameters

usePaymentMethods() accepts a single optional object with the following properties:

  • Name
    enabled?
    Type
    boolean
    Description

    If true, a request will be triggered when the hook is mounted. Defaults to true.

  • Name
    for?
    Type
    "user" | "organization"
    Description

    Specifies whether to fetch for the current user or Organization. Defaults to 'user'.

  • Name
    infinite?
    Type
    boolean
    Description

    If true, newly fetched data will be appended to the existing list rather than replacing it. Useful for implementing infinite scroll functionality. Defaults to false.

  • Name
    initialPage?
    Type
    number
    Description

    A number that specifies which page to fetch. For example, if initialPage is set to 10, it will skip the first 9 pages and fetch the 10th page. Defaults to 1.

  • Name
    keepPreviousData?
    Type
    boolean
    Description

    If true, the previous data will be kept in the cache until new data is fetched. Defaults to false.

  • Name
    pageSize?
    Type
    number
    Description

    A number that specifies the maximum number of results to return per page. Defaults to 10.

Returns

usePaymentMethods() returns an object with the following properties:

  • Name
    count
    Type
    number
    Description

    The total count of data that exist remotely.

  • Name
    data
    Type
    BillingPaymentMethodResource[]
    Description

    An array that contains the fetched data. For example, for the memberships attribute, data will be an array of OrganizationMembership objects.

  • Name
    error
    Type
    null | ClerkAPIResponseError
    Description

    Clerk's API response error object.

  • Name
    fetchNext
    Type
    () => void
    Description

    A function that triggers the next page to be loaded. This is the same as fetchPage(page => Math.min(pageCount, page + 1)).

  • Name
    fetchPage
    Type
    ValueOrSetter<number>
    Description

    A function that triggers a specific page to be loaded.

  • Name
    fetchPrevious
    Type
    () => void
    Description

    A function that triggers the previous page to be loaded. This is the same as fetchPage(page => Math.max(0, page - 1)).

  • Name
    hasNextPage
    Type
    boolean
    Description

    Indicates whether there are available pages to be fetched.

  • Name
    hasPreviousPage
    Type
    boolean
    Description

    Indicates whether there are available pages to be fetched.

  • Name
    isError
    Type
    boolean
    Description

    Indicates whether the request failed.

  • Name
    isFetching
    Type
    boolean
    Description

    Indicates whether there is an ongoing request or a revalidation.

  • Name
    isLoading
    Type
    boolean
    Description

    Indicates whether there is an ongoing request and there is no fetched data.

  • Name
    page
    Type
    number
    Description

    The current page.

  • Name
    pageCount
    Type
    number
    Description

    The total amount of pages. It is calculated based on count, initialPage, and pageSize.

  • Name
    revalidate
    Type
    () => Promise<void>
    Description

    A function that triggers a revalidation of the current page.

  • Name
    setData
    Type
    CacheSetter<undefined | ClerkPaginatedResponse<BillingPaymentMethodResource>>
    Description

    A function that allows you to set the data manually.

Examples

Basic usage

The following example demonstrates how to fetch and display a user's payment methods.

src/pages/billing/PaymentMethodsList.tsx
import { usePaymentMethods } from '@clerk/react/experimental'

export default function PaymentMethodsList() {
  const { data, isLoading } = usePaymentMethods({
    for: 'user',
    pageSize: 10,
  })

  if (isLoading) {
    return <div>Loading payment methods...</div>
  }

  if (!data || data.length === 0) {
    // Code for how to add a new payment method: https://clerk.com/docs/guides/development/custom-flows/billing/add-new-payment-method
    return <div>No payment methods found. Please add a payment method to your account.</div>
  }

  return (
    <ul>
      {data?.map((method) => (
        <li key={method.id}>
          {method.cardType} **** {method.last4}
          {method.isDefault ? ' (Default)' : null}
        </li>
      ))}
    </ul>
  )
}

Infinite pagination

The following example demonstrates how to implement infinite scrolling with payment methods.

src/pages/billing/PaymentMethodsList.tsx
import { usePaymentMethods } from '@clerk/react/experimental'

export default function InfinitePaymentMethods() {
  const { data, isLoading, hasNextPage, fetchNext } = usePaymentMethods({
    for: 'user',
    infinite: true,
    pageSize: 20,
  })

  if (isLoading) {
    return <div>Loading...</div>
  }

  if (!data || data.length === 0) {
    // Code for how to add a new payment method: https://clerk.com/docs/guides/development/custom-flows/billing/add-new-payment-method
    return <div>No payment methods found. Please add a payment method to your account.</div>
  }

  return (
    <div>
      <ul>
        {data?.map((method) => (
          <li key={method.id}>
            {method.cardType} ending in {method.last4}
            {method.status === 'expired' ? ' (Expired)' : null}
            {method.status === 'disconnected' ? ' (Disconnected)' : null}
          </li>
        ))}
      </ul>

      {hasNextPage && <button onClick={() => fetchNext()}>Load more payment methods</button>}
    </div>
  )
}

With checkout flow

The following example demonstrates how to use usePaymentMethods() in a checkout flow to select an existing payment method. For more information on how to build a checkout flow with an existing payment method, see Build a custom checkout flow.

src/pages/billing/CheckoutPaymentSelection.tsx
import { usePaymentMethods, useCheckout } from '@clerk/react/experimental'
import { useNavigate } from 'react-router-dom'

export default function CheckoutPaymentSelection() {
  const { data, isLoading } = usePaymentMethods({ for: 'user' })
  const { checkout } = useCheckout()
  const navigate = useNavigate()

  const handlePaymentSubmit = async (paymentMethodId: string) => {
    try {
      // Confirm checkout with selected payment method
      const { error } = await checkout.confirm({ paymentMethodId })
      if (error) {
        console.error(JSON.stringify(error, null, 2))
        return
      }
      // Complete checkout and redirect
      await checkout.finalize({
        navigate: ({ decorateUrl }) => {
          const url = decorateUrl('/')
          if (url.startsWith('http')) {
            window.location.href = url
          } else {
            navigate(url)
          }
        },
      })
    } catch (error) {
      console.error('Payment failed:', error)
    }
  }

  if (isLoading) {
    return <div>Loading payment methods...</div>
  }

  if (!data || data.length === 0) {
    // Code for how to add a new payment method: https://clerk.com/docs/guides/development/custom-flows/billing/checkout-new-payment-method
    return <div>No payment methods found. Please add a payment method to your account.</div>
  }

  return (
    <div>
      <h3>Select a payment method</h3>
      {data?.map((method) => (
        <button key={method.id} onClick={() => handlePaymentSubmit(method.id)}>
          Pay with {method.cardType} ending in {method.last4}
        </button>
      ))}
    </div>
  )
}

Checkout flow with a new payment method

Build a custom checkout flow that allows users to add a new payment method during checkout.

Add a new payment method outside of a checkout flow

Build a custom user interface that allows users to add a new payment method to their account.

Feedback

What did you think of this content?

Last updated on