React Stripe.js

repository·master·Indexed 24 days ago

https://github.com/stripe/react-stripe-js

React components and hooks for integrating Stripe.js and Stripe Elements into React applications. Version 6.8.0 provides tools for secure payment collection, including the <Elements> provider, useStripe and useElements hooks, and support for both functional and class-based components. Requires React v16.8 or higher.

Tokens
12.1K
Snippets
20
Records
54
Agent score
83%

What's inside @stripe/react-stripe-js

  1. Migrate from `react-stripe-elements` to React Stripe.js

    master

    To migrate from the legacy react-stripe-elements library to React Stripe.js, follow these steps:

    1. Install dependencies: Remove react-stripe-elements and install @stripe/react-stripe-js and @stripe/stripe-js.
    2. Update imports: Change imports from react-stripe-elements to @stripe/react-stripe-js.
    3. Replace <StripeProvider>: Instead of using <StripeProvider>, use loadStripe from @stripe/stripe-js to create a stripePromise, then pass that promise to the <Elements> component via the stripe prop.
    4. Update Element options: Element configuration options (like style or iconStyle) are no longer passed as direct props. They must now be passed within an options prop object.
    5. Switch to Hooks: Replace the injectStripe Higher Order Component with the useStripe and useElements hooks. Alternatively, use <ElementsConsumer> if you cannot use hooks.
    6. Explicit Element references: React Stripe.js does not automatically detect Elements. You must use elements.getElement(CardElement) to retrieve a reference to the mounted element and pass it explicitly to Stripe.js methods like stripe.createToken(cardElement) or stripe.createPaymentMethod({ card: cardElement, ... }).
    npm uninstall react-stripe-elements
    npm install @stripe/react-stripe-js @stripe/stripe-js
  2. Configure TypeScript support

    master
    React Stripe.js includes built-in TypeScript declarations. To ensure full type safety, you must also install @stripe/stripe-js as a dependency in your project, as some types are exported from that package. The typings follow the same versioning policy as @stripe/stripe-js.
  3. Update Element component options

    master

    In React Stripe.js, configuration options for Elements (such as style or iconStyle) must be wrapped in an options prop, rather than being passed as top-level props.

    import {CardElement} from '@stripe/react-stripe-js';
    
    <CardElement
      id="my-card"
      onChange={handleChange}
      {/* Options are passed in on their own prop. */}
      options={{
        iconStyle: 'solid',
        style: {
          base: {
            iconColor: '#c4f0ff',
            color: '#fff',
            fontSize: '16px',
          },
          invalid: {
            iconColor: '#FFC7EE',
            color: '#FFC7EE',
          },
        },
      }}
    />;
  4. Replace `<StripeProvider>` with `<Elements>` and `loadStripe`

    master

    React Stripe.js removes the <StripeProvider> component. You must now instantiate the Stripe object yourself using loadStripe and pass the resulting promise to the <Elements> component.

    import {loadStripe} from '@stripe/stripe-js';
    import {Elements} from '@stripe/react-stripe-js';
    
    // Create the Stripe object yourself...
    const stripePromise = loadStripe('pk_test_6pRNASCoBOKtIshFeQd4XMUh');
    
    const App = () => (
      // ...and pass it directly to <Elements>.
      <Elements stripe={stripePromise}>{/* Your checkout form */}</Elements>
    );
  5. Use Checkout Elements in React

    master
    The src/checkout/index.ts entrypoint provides several specialized React components for building Stripe checkout flows. These components are designed to be used within a checkout context to handle specific parts of the payment process, such as address collection, payment methods, and tax information.
  6. Common props for all Stripe Elements

    master

    All Stripe Element components inherit from ElementProps, which provides standard HTML attributes and lifecycle events for the element's container:

    • id: The ID for the element's container.
    • className: The CSS class for the element's container.
    • onBlur: Triggered when the Element loses focus. Receives an event containing the elementType.
    • onFocus: Triggered when the Element receives focus. Receives an event containing the elementType.
    export interface ElementProps {
      id?: string;
      className?: string;
      onBlur?: (event: {elementType: stripeJs.StripeElementType}) => any;
      onFocus?: (event: {elementType: stripeJs.StripeElementType}) => any;
    }
  7. Use the <Elements> provider to wrap your application

    master

    The <Elements> component is a provider that allows you to use Element components and access the Stripe object in any nested component.

    To use it, call loadStripe from @stripe/stripe-js with your publishable key and pass the resulting promise to the stripe prop.

    Important constraints:

    • Once the stripe prop has been set, it cannot be changed. Changing it will trigger a console warning.
    • You can pass null or a Promise resolving to null for initial server-side rendering or static site generation.
    • The options prop (used for StripeElementsOptions) can only be updated for specific keys like clientSecret and fonts via internal logic; generally, the configuration is established at initialization.
  8. Implement a checkout form using Class Components

    master

    For class-based components, use the <ElementsConsumer> component to inject the stripe and elements instances into your component via props.

    Key steps:

    1. Wrap your component in <ElementsConsumer>.
    2. The consumer provides {stripe, elements} as an argument to its render function.
    3. Pass these instances as props to your class component.
    4. Access them via this.props.stripe and this.props.elements.
    import React from 'react';
    import ReactDOM from 'react-dom';
    import {loadStripe} from '@stripe/stripe-js';
    import {
      PaymentElement,
      Elements,
      ElementsConsumer,
    } from '@stripe/react-stripe-js';
    
    class CheckoutForm extends React.Component {
      handleSubmit = async (event) => {
        event.preventDefault();
        const {stripe, elements} = this.props;
    
        if (elements == null) {
          return;
        }
    
        // Trigger form validation and wallet collection
        const {error: submitError} = await elements.submit();
        if (submitError) {
          // Show error to your customer
          return;
        }
    
        // Create the PaymentIntent and obtain clientSecret
        const res = await fetch('/create-intent', {
          method: 'POST',
        });
    
        const {client_secret: clientSecret} = await res.json();
    
        const {error} = await stripe.confirmPayment({
          //`Elements` instance that was used to create the Payment Element
          elements,
          clientSecret,
          confirmParams: {
            return_url: 'https://example.com/order/123/complete',
          },
        });
    
        if (error) {
          // This point will only be reached if there is an immediate error when
          // confirming the payment. Show error to your customer (for example, payment
          // details incomplete)
        } else {
          // Your customer will be redirected to your `return_url`.
        }
      };
    
      render() {
        const {stripe} = this.props;
        return (
          <form onSubmit={this.handleSubmit}>
            <PaymentElement />
            <button type="submit" disabled={!stripe}>
              Pay
            </button>
          </form>
        );
      }
    }
    
    const InjectedCheckoutForm = () => (
      <ElementsConsumer>
        {({stripe, elements}) => (
          <CheckoutForm stripe={stripe} elements={elements} />
        )}
      </ElementsConsumer>
    );
    
    const stripePromise = loadStripe('pk_test_6pRNASCoBOKtIshFeQd4XMUh');
    
    const options = {
      mode: 'payment',
      amount: 1099,
      currency: 'usd',
      // Fully customizable with appearance API.
      appearance: {
        /*...*/
      },
    };
    
    const App = () => (
      <Elements stripe={stripePromise} options={options}>
        <InjectedCheckoutForm />
      </Elements>
    );
    
    ReactDOM.render(<App />, document.body);
  9. Implement a checkout form using Hooks

    master

    You can use the useStripe and useElements hooks to access the Stripe instance and the Elements instance within a component wrapped by <Elements>. This is the recommended approach for functional components.

    Key steps in the workflow:

    1. Initialize Stripe using loadStripe outside your component.
    2. Wrap your application (or checkout section) in the <Elements> provider, passing the stripe promise and an options object.
    3. Use useStripe() to get the Stripe object for confirming payments.
    4. Use useElements() to get the Elements object for triggering validation via elements.submit().
    5. Use stripe.confirmPayment to complete the transaction.
    import React, {useState} from 'react';
    import ReactDOM from 'react-dom';
    import {loadStripe} from '@stripe/stripe-js';
    import {
      PaymentElement,
      Elements,
      useStripe,
      useElements,
    } from '@stripe/react-stripe-js';
    
    const CheckoutForm = () => {
      const stripe = useStripe();
      const elements = useElements();
    
      const [errorMessage, setErrorMessage] = useState(null);
    
      const handleSubmit = async (event) => {
        event.preventDefault();
    
        if (elements == null) {
          return;
        }
    
        // Trigger form validation and wallet collection
        const {error: submitError} = await elements.submit();
        if (submitError) {
          // Show error to your customer
          setErrorMessage(submitError.message);
          return;
        }
    
        // Create the PaymentIntent and obtain clientSecret from your server endpoint
        const res = await fetch('/create-intent', {
          method: 'POST',
        });
    
        const {client_secret: clientSecret} = await res.json();
    
        const {error} = await stripe.confirmPayment({
          //`Elements` instance that was used to create the Payment Element
          elements,
          clientSecret,
          confirmParams: {
            return_url: 'https://example.com/order/123/complete',
          },
        });
    
        if (error) {
          // This point will only be reached if there is an immediate error when
          // confirming the payment. Show error to your customer (for example, payment
          // details incomplete)
          setErrorMessage(error.message);
        } else {
          // Your customer will be redirected to your `return_url`.
        }
      };
    
      return (
        <form onSubmit={handleSubmit}>
          <PaymentElement />
          <button type="submit" disabled={!stripe || !elements}>
            Pay
          </button>
          {/* Show error message to your customers */}
          {errorMessage && <div>{errorMessage}</div>}
        </form>
      );
    };
    
    const stripePromise = loadStripe('pk_test_6pRNASCoBOKtIshFeQd4XMUh');
    
    const options = {
      mode: 'payment',
      amount: 1099,
      currency: 'usd',
      // Fully customizable with appearance API.
      appearance: {
        /*...*/
      },
    };
    
    const App = () => (
      <Elements stripe={stripePromise} options={options}>
        <CheckoutForm />
      </Elements>
    );
    
    ReactDOM.render(<App />, document.body);
  10. Use `useStripe` and `useElements` hooks

    master

    React Stripe.js uses React Hooks instead of the injectStripe Higher Order Component to provide access to the Stripe instance and the Elements instance.

    import {useStripe, useElements} from '@stripe/react-stripe-js';
    
    const CheckoutForm = (props) => {
      // Get a reference to Stripe or Elements using hooks.
      const stripe = useStripe();
      const elements = useElements();
    
      // the rest of CheckoutForm...
    };