fix: only load stripe once (#52921)
parent
b4a550966b
commit
e1816b6d06
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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;
|
Loading…
Reference in New Issue