Reputation: 55
I am making a Stripe promise in React, their docs say to load the promise outside of the component like so:
import {Elements} from '@stripe/react-stripe-js';
import {loadStripe} from '@stripe/stripe-js';
// Make sure to call `loadStripe` outside of a component’s render to avoid
// recreating the `Stripe` object on every render.
const stripePromise = loadStripe('pk_test_TYooMQauvdEDq54NiTphI7jx');
const App = () => {
return (
<Elements stripe={stripePromise}>
<MyCheckoutForm />
</Elements>
);
};
My problem is that I'm getting the public key from an API and storing it in redux (we connect to several different companies). Loading it within the component is causing re-renders:
import React from "react";
import { Elements } from "@stripe/react-stripe-js";
import { loadStripe } from "@stripe/stripe-js";
import { useSelector } from "react-redux";
import ExpressCheckout from "./ExpressCheckout";
const ExpressContainer = () => {
const stripe_PK = useSelector(
(state) => state.company.presenter.data_stripe_pk
);
const stripePromise = loadStripe(stripe_PK);
return (
<Elements stripe={stripePromise}>
<ExpressCheckout />
</Elements>
);
};
export default ExpressContainer;
I've tried to load the redux state before the component with getState() but it comes back blank.
Upvotes: 2
Views: 2245
Reputation: 7459
You'll want to defer calling loadStripe
until you get a valid value for the PK out of your selector.
When you provide null
to the stripe
prop of <Elements />
, it defers initialization. You can change one time from a null value to a promise that resolves to a Stripe object, but then changing the stripe
prop is not allowed.
stripe
required Stripe | null | Promise<Stripe | null>
A Stripe object or a Promise resolving to a Stripe object. The easiest way to initialize a Stripe object is with the Stripe.js wrapper module. After this prop has been set, it can not be changed.
You can also pass in null or a Promise resolving to null if you’re performing an initial server-side render or when generating a static site.
I've rigged up an example here with setTimeout
to simulate a delayed load of the key and then useEffect
to trigger calling loadStripe
:
https://codesandbox.io/s/react-stripe-js-delayed-key-effect-boxmz
This is not the only way to achieve this, but it illustrates the idea.
Upvotes: 2