Skip to content

useStripe ​

Access the Stripe instance from any component within VueStripeProvider.

What is useStripe? ​

A composable that provides access to the Stripe.js instance from any child component:

CapabilityDescription
Stripe Instance AccessGet the initialized Stripe.js instance for API calls
Loading StateKnow when Stripe.js is still loading
Error StateDetect if Stripe.js failed to load
Reactive UpdatesValues update automatically when Stripe loads
Type SafetyFull TypeScript support with proper typing

How It Works ​

mermaid
flowchart TD
    A["Component calls useStripe()"] --> B["Composable checks for StripeProvider context<br/>(Uses Vue's inject with stripeInjectionKey)"]
    B --> C{Context Found?}
    C -->|Yes| D["<b>Context Found</b><br/>Returns { stripe, loading, error }"]
    C -->|No| E["<b>No Context Found</b><br/>Throws Error:<br/>'useStripe must be called within<br/>a VueStripeProvider component'"]
    D --> F["Component uses stripe.value for API calls<br/><br/>if (stripe.value) {<br/>  await stripe.value.confirmPayment({ ... })<br/>}"]

Usage ​

vue
<script setup>
import { useStripe } from '@vue-stripe/vue-stripe'

// Must be called inside a component that's within VueStripeProvider
const { stripe, loading, error } = useStripe()
</script>

Return Value ​

PropertyTypeDescription
stripeReadonly<Ref<Stripe | null>>The Stripe instance
loadingReadonly<Ref<boolean>>True while Stripe.js is loading
errorReadonly<Ref<string | null>>Error message if loading failed
initialize() => Promise<void>No-op kept for API consistency; initialization is handled by the provider.

All return values are readonly refs - you can read their .value but cannot modify them.

Examples ​

Basic Usage ​

vue
<script setup>
import { useStripe } from '@vue-stripe/vue-stripe'

const { stripe, loading, error } = useStripe()

const confirmPayment = async () => {
  if (!stripe.value) return

  const result = await stripe.value.confirmPayment({
    // ...
  })
}
</script>

<template>
  <div v-if="loading">Loading...</div>
  <div v-else-if="error">{{ error }}</div>
  <button v-else @click="confirmPayment">Pay</button>
</template>

Watching for Stripe Ready ​

vue
<script setup>
import { watch } from 'vue'
import { useStripe } from '@vue-stripe/vue-stripe'

const { stripe } = useStripe()

watch(stripe, (newStripe) => {
  if (newStripe) {
    console.log('Stripe is now available!')
  }
})
</script>

In a Computed Property ​

vue
<script setup>
import { computed } from 'vue'
import { useStripe } from '@vue-stripe/vue-stripe'

const { stripe, loading, error } = useStripe()

const isReady = computed(() => {
  return !loading.value && !error.value && stripe.value !== null
})
</script>

Creating Payment Methods ​

vue
<script setup>
import { useStripe, useStripeElements } from '@vue-stripe/vue-stripe'

const { stripe } = useStripe()
const { elements } = useStripeElements()

const createPaymentMethod = async () => {
  if (!stripe.value || !elements.value) return

  const cardElement = elements.value.getElement('card')

  const { error, paymentMethod } = await stripe.value.createPaymentMethod({
    type: 'card',
    card: cardElement
  })

  if (error) {
    console.error(error)
  } else {
    console.log('Created payment method:', paymentMethod.id)
  }
}
</script>

Retrieving a PaymentIntent ​

vue
<script setup>
import { onMounted } from 'vue'
import { useStripe } from '@vue-stripe/vue-stripe'

const { stripe } = useStripe()

onMounted(async () => {
  // Wait for Stripe to be ready
  if (!stripe.value) return

  const clientSecret = new URLSearchParams(window.location.search).get(
    'payment_intent_client_secret'
  )

  if (clientSecret) {
    const { paymentIntent } = await stripe.value.retrievePaymentIntent(
      clientSecret
    )
    console.log('Payment status:', paymentIntent?.status)
  }
})
</script>

Error Handling ​

useStripe() throws an error if called outside of VueStripeProvider:

vue
<!-- ❌ Wrong - useStripe() called outside StripeProvider -->
<script setup>
const { stripe } = useStripe() // Throws: "useStripe must be called within a VueStripeProvider component"
</script>

<template>
  <VueStripeProvider :publishable-key="key">
    <MyForm />
  </VueStripeProvider>
</template>
vue
<!-- ✅ Correct - create a child component -->
<!-- MyForm.vue -->
<script setup>
const { stripe } = useStripe() // Works!
</script>

<!-- Parent.vue -->
<template>
  <VueStripeProvider :publishable-key="key">
    <MyForm />
  </VueStripeProvider>
</template>

TypeScript ​

ts
import { useStripe } from '@vue-stripe/vue-stripe'
import type { Stripe, PaymentIntentResult } from '@stripe/stripe-js'

const { stripe, loading, error } = useStripe()

// stripe.value is typed as Stripe | null
const confirmPayment = async (): Promise<PaymentIntentResult | undefined> => {
  if (!stripe.value) return

  return stripe.value.confirmPayment({
    elements: elements.value!,
    confirmParams: {
      return_url: 'https://example.com/complete'
    }
  })
}

Common Patterns ​

Safe Stripe Access ​

ts
const safeConfirm = async () => {
  const s = stripe.value
  if (!s) {
    console.error('Stripe not initialized')
    return
  }

  // TypeScript now knows s is Stripe, not null
  const result = await s.confirmPayment({ ... })
}

With Loading State ​

vue
<script setup>
const { stripe, loading } = useStripe()
const processing = ref(false)

const handleSubmit = async () => {
  if (!stripe.value) return

  processing.value = true
  try {
    await stripe.value.confirmPayment({ ... })
  } finally {
    processing.value = false
  }
}
</script>

<template>
  <button
    @click="handleSubmit"
    :disabled="loading || processing"
  >
    {{ loading ? 'Loading...' : processing ? 'Processing...' : 'Pay' }}
  </button>
</template>

See Also ​

Released under the MIT License.