fix: only load stripe once (#52921)

pull/52913/head^2
Oliver Eyton-Williams 2024-01-04 16:24:10 +01:00 committed by GitHub
parent b4a550966b
commit e1816b6d06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 39 additions and 60 deletions

View File

@ -3,8 +3,10 @@ import PropTypes from 'prop-types';
import React from 'react';
import { I18nextProvider } from 'react-i18next';
import { Provider } from 'react-redux';
import { Elements } from '@stripe/react-stripe-js';
import i18n from './i18n/config';
import { stripe } from './src/utils/stripe';
import AppMountNotifier from './src/components/app-mount-notifier';
import { createStore } from './src/redux/create-store';
import layoutSelector from './utils/gatsby/layout-selector';
@ -17,7 +19,9 @@ export const wrapRootElement = ({ element }) => {
<Provider store={store}>
<I18nextProvider i18n={i18n}>
<GrowthBookProvider>
<AppMountNotifier>{element}</AppMountNotifier>
<AppMountNotifier>
<Elements stripe={stripe}>{element}</Elements>
</AppMountNotifier>
</GrowthBookProvider>
</I18nextProvider>
</Provider>

View File

@ -2,8 +2,10 @@ import PropTypes from 'prop-types';
import React from 'react';
import { I18nextProvider } from 'react-i18next';
import { Provider } from 'react-redux';
import { Elements } from '@stripe/react-stripe-js';
import i18n from './i18n/config';
import { stripe } from './src/utils/stripe';
import { createStore } from './src/redux/create-store';
import layoutSelector from './utils/gatsby/layout-selector';
import { getheadTagComponents, getPostBodyComponents } from './utils/tags';
@ -15,7 +17,9 @@ export const wrapRootElement = ({ element }) => {
return (
<Provider store={store}>
<I18nextProvider i18n={i18n}>
<GrowthBookProvider>{element}</GrowthBookProvider>
<GrowthBookProvider>
<Elements stripe={stripe}>{element}</Elements>
</GrowthBookProvider>
</I18nextProvider>
</Provider>
);

View File

@ -2,10 +2,8 @@ import {
CardNumberElement,
CardExpiryElement,
useStripe,
useElements,
Elements
useElements
} from '@stripe/react-stripe-js';
import { loadStripe } from '@stripe/stripe-js';
import type {
StripeCardNumberElementChangeEvent,
StripeCardExpiryElementChangeEvent
@ -13,12 +11,9 @@ import type {
import React, { useState } from 'react';
import { PaymentProvider } from '../../../../shared/config/donation-settings';
import envData from '../../../config/env.json';
import { Themes } from '../settings/theme';
import { DonationApprovalData, PostPayment } from './types';
const { stripePublicKey }: { stripePublicKey: string | null } = envData;
interface FormPropTypes {
onDonationStateChange: (donationState: DonationApprovalData) => void;
postPayment: (arg0: PostPayment) => void;
@ -35,13 +30,13 @@ interface Element {
type PaymentInfoValidation = Element[];
const StripeCardForm = ({
export default function StripeCardForm({
theme,
t,
onDonationStateChange,
postPayment,
processing
}: FormPropTypes): JSX.Element => {
}: FormPropTypes): JSX.Element {
const [isSubmissionValid, setSubmissionValidity] = useState(true);
const [isTokenizing, setTokenizing] = useState(false);
const [paymentInfoValidation, setPaymentValidity] =
@ -167,18 +162,4 @@ const StripeCardForm = ({
</button>
</form>
);
};
const CardFormWrapper = (props: FormPropTypes): JSX.Element | null => {
if (!stripePublicKey) {
return null;
} else {
return (
<Elements stripe={loadStripe(stripePublicKey)}>
<StripeCardForm {...props} />
</Elements>
);
}
};
export default CardFormWrapper;
}

View File

@ -1,18 +1,14 @@
import {
PaymentRequestButtonElement,
Elements,
ElementsConsumer
} from '@stripe/react-stripe-js';
import { Stripe, loadStripe } from '@stripe/stripe-js';
import type { Token, PaymentRequest } from '@stripe/stripe-js';
import type { Token, PaymentRequest, Stripe } from '@stripe/stripe-js';
import React, { useState, useEffect } from 'react';
import envData from '../../../config/env.json';
import { Themes } from '../settings/theme';
import { PaymentProvider } from '../../../../shared/config/donation-settings';
import { DonationApprovalData, PostPayment } from './types';
const { stripePublicKey }: { stripePublicKey: string | null } = envData;
interface WrapperProps {
label: string;
amount: number;
@ -113,25 +109,12 @@ const WalletsButton = ({
);
};
const InjectedCheckoutForm = (props: WrapperProps): JSX.Element => (
<ElementsConsumer>
{({ stripe }: { stripe: Stripe | null }) => (
<WalletsButton stripe={stripe} {...props} />
)}
</ElementsConsumer>
);
const WalletsWrapper = (props: WrapperProps): JSX.Element | null => {
if (!stripePublicKey) {
return null;
} else {
const stripePromise = loadStripe(stripePublicKey);
return (
<Elements stripe={stripePromise}>
<InjectedCheckoutForm {...props} />
</Elements>
);
}
};
export default WalletsWrapper;
export default function InjectedCheckoutForm(props: WrapperProps): JSX.Element {
return (
<ElementsConsumer>
{({ stripe }: { stripe: Stripe | null }) => (
<WalletsButton stripe={stripe} {...props} />
)}
</ElementsConsumer>
);
}

View File

@ -9,9 +9,6 @@ import {
takeLeading
} from 'redux-saga/effects';
import { loadStripe } from '@stripe/stripe-js';
import envData from '../../config/env.json';
import {
addDonation,
postChargeStripe,
@ -19,6 +16,7 @@ import {
updateStripeCard
} from '../utils/ajax';
import { stringifyDonationEvents } from '../utils/analytics-strings';
import { stripe } from '../utils/stripe';
import { PaymentProvider } from '../../../shared/config/donation-settings';
import { actionTypes as appTypes } from './action-types';
import {
@ -42,8 +40,6 @@ import {
const defaultDonationErrorMessage = i18next.t('donate.error-2');
const updateCardErrorMessage = i18next.t('donate.error-3');
const { stripePublicKey } = envData;
function* showDonateModalSaga() {
let shouldRequestDonation = yield select(shouldRequestDonationSelector);
if (shouldRequestDonation) {
@ -172,8 +168,7 @@ export function* updateCardSaga() {
} = yield call(updateStripeCard);
if (!sessionId) throw new Error('No sessionId');
const stripe = yield call(loadStripe, stripePublicKey);
stripe.redirectToCheckout({ sessionId });
(yield stripe).redirectToCheckout({ sessionId });
} catch (error) {
yield put(updateCardError(updateCardErrorMessage));
}

View File

@ -20,6 +20,11 @@ import {
jest.mock('../utils/ajax');
jest.mock('../analytics');
jest.mock('../utils/stripe', () => ({
stripe: Promise.resolve({
redirectToCheckout: jest.fn()
})
}));
const postChargeDataMock = {
payload: {

View File

@ -0,0 +1,7 @@
import { loadStripe } from '@stripe/stripe-js';
import envData from '../../config/env.json';
const { stripePublicKey } = envData;
export const stripe = stripePublicKey ? loadStripe(stripePublicKey) : null;