Stripe Payment is completely work but i got the warning message on the console, "Unsupported prop change on Elements: You cannot change the stripe
prop after setting it."
Here is my code. I have no idea why the warning message is showing, what do i miss?
const Parent =() => {
const stripePromise = loadStripe(PUBLISHABLE_KEY);
<Elements stripe ={stripePromise}>
<Child_component/>
</Elements>
}
export default Parent;
import {CardNumberElement, CardExpiryElement, CardCvcElement} from '@stripe/react-stripe-js';
const Child_component =() => {
const handleChange = (event) => {
//get the brand type
};
const handleFormSubmit = async ev =>{
const cardElement = elements.getElement(CardNumberElement);
const paymentMethodReq = await stripe.createPaymentMethod({
type: 'card',
card: cardElement
});
/// and send paymentMethodReq to the backend.
}
render(
<Form className="" onSubmit={handleFormSubmit}>
<div className="split-form full-width inline-block pt-4">
<div className="row">
<div className="col-12">
<label className="card-element">
Card number
<CardNumberElement
className="cardNumberElement"
onChange={handleChange}
/>
</label>
</div>
<div className="col-8">
<label className="card-element">
Expiration date
<CardExpiryElement
onChange={handleChange}
/>
</label>
</div>
<div className="col-4">
<label className="card-element">
CVC
<CardCvcElement
onChange={handleChange}
/>
</label>
</div>
</div>
</div>
</Form>
)
}
export default Child_component;
To remount a component when a prop changes, use the React key attribute as described in this post on the React blog: When a key changes, React will create a new component instance rather than update the current one. The example below shows how the key attribute can be used.
The guide will start with a very simple label component that will have a prop called text and display it inside a span, then extend this component to highlight the text when the prop is changed by the parent component.
This can be achieved by passing an empty array as the second parameter and returning a function that will then be called when the component is being umounted. The code for this looks like: Add these two calls to useEffect into the Label function and the background color will now highlight for a second whenever the text prop changes.
Your problem is that in your Parent
component you just do
const stripePromise = loadStripe(PUBLISHABLE_KEY);
What it means is actually on each render you will get new promise object (new stripePromise
) every time, that's exactly what <Element>
component is complaining about. What you should do instead, to not get new instance all the time on render, you should put loadStripe function in state, but because it is a function, you actually need to wrap it up in another function because of this - https://reactjs.org/docs/hooks-reference.html#lazy-initial-state.
So how should look like:
const [stripePromise, setStripePromise] = useState(() => loadStripe(PUBLISHABLE_KEY))
I had the same error.
what if we move the stripePromise variable outside the functional component? – Noman Gul Feb 5 at 17:35
Noman's comment is the ideal solution for most of cases, but that doesn't work if the Stripe account depends on React state. This usually happens if you are building apps with Stripe Connect.
In that case, you should use useMemo
to memoize the promise.
const Parent = ({ stripeAccount }) => {
const stripePromise = useMemo(
() => loadStripe(PUBLISHABLE_KEY, { stripeAccount }),
[stripeAccount],
)
return (
<Elements stripe={stripePromise}>
<Child_component/>
</Elements>
)
}
Otherwise, the component loads stripe every re-render!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With