I am using the PaymentElement to accept payments. The problem is after a clientSecret is generated, and the amount is updated on my website it doesn’t reflect the update amount. The only way it will reflect if the page is reloaded.
Is there anyway where i can have the amount updated? Below is my code. Any help would be really appreciated. Below is my code
import React, { useState, useEffect } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import CheckoutForm from '../../components/CheckoutForm'; // Adjust the path as needed
import { loadStripe } from '@stripe/stripe-js';
import { Elements } from '@stripe/react-stripe-js';
import { useParams } from 'next/navigation';
import { useSelector } from 'react-redux';
export default function CheckoutPage() {
const storeInfo = useSelector((state) => state.storeInfo);
const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY);
const [clientSecret, setClientSecret] = useState(null);
const params = useParams();
const storeId = params.store_id;
const grandTotal = useSelector((state) => state.cart.grandTotal); // Assuming it's in the cart slice
useEffect(() => {
const grandTotalInCents = Math.round(grandTotal * 100);
const fetchClientSecret = async () => {
try {
const response = await fetch('/api/checkout/create-payment-intent', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
amount: grandTotalInCents, // Dummy amount in cents
name: 'Dummy User', // Dummy name
email : "[email protected]"
}),
});
const data = await response.json();
if (data.clientSecret) {
setClientSecret(data.clientSecret);
} else {
console.error('Failed to retrieve client secret:', data);
}
} catch (error) {
console.error('Error fetching client secret:', error);
}
};
fetchClientSecret();
}, [grandTotal]); // Dependency array ensures this runs when grandTotal changes
return (
<div className="container mt-5">
<div className="d-flex justify-content-end mb-3"></div>
{stripePromise && clientSecret && (
<Elements stripe={stripePromise} options={{ clientSecret }}>
<CheckoutForm clientSecrett={clientSecret} />
</Elements>
)}
</div>
);
}
2
Answers
Stripe’s Elements doesn’t reinitialize automatically when the clientSecret changes. To handle this:
Key Prop on Elements Component: React will treat Elements as a new component if the key prop changes. By using clientSecret as the key, React will re-render the Elements component whenever clientSecret changes.
Update your Elements wrapper like so:
This ensures the Elements component re-initializes when a new clientSecret is fetched.
Make sure your backend endpoint /api/checkout/create-payment-intent correctly creates a PaymentIntent with the provided amount.
You should just call elements.fetchUpdates() to reflect the updates on the existing Payment Element.