#abjeet__singh
1 messages · Page 1 of 1 (latest)
Are you following a guide currently?
Can you copy/paste the exact error message you're getting?
sure
Error occurred prerendering page "/CheckoutForm". Read more: https://nextjs.org/docs/messages/prerender-error
Error: Could not find Elements context; You need to wrap the part of your app that calls useStripe() in an <Elements> provider.
at parseElementsContext (/Users/abjeetsingh/Coding/client/node_modules/@stripe/react-stripe-js/dist/react-stripe.js:504:11)
at useElementsOrCustomCheckoutSdkContextWithUseCase
the error occurs while executing NPM RUN BUILD
the code works fine for NPM RUN DEV
I'm confused about what this line is doing --> clientSecret && stripePromise &&
You are already passing the clientSecret and stripePromise into the Elements provider, so do you need this here for some reason? Can you try removing it? It's the only part of the code that might cause issue by being outside of the Elements provider, so that's my best guess right now
am ensuring if the clientSecret and StripePromise are correctly populated or not...
since they are both asynchronously fetched from the server.
kindly suggest if removing them might resolve the issue
You should try and see
no improvement
return (
<div className="p-14">
{costing && <CurrencyChange ammount={costing} />}
<Elements stripe={stripePromise} options={{ clientSecret }}>
<CheckoutForm props={[query, costing]} />
</Elements>
</div>
);
this is the updated code, it still yields the same error.
Thank you, looking in to what may be happening here as well
Can you send the code for your CheckoutForm as well?
sure,
import { PaymentElement } from "@stripe/react-stripe-js";
import { useState } from "react";
import { useStripe, useElements } from "@stripe/react-stripe-js";
export default function CheckoutForm(props) {
const { query, cost } = props;
const stripe = useStripe();
const elements = useElements();
const [message, setMessage] = useState(null);
const [isProcessing, setIsProcessing] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
if (!stripe || !elements) {
// Stripe.js has not yet loaded.
// Make sure to disable form submission until Stripe.js has loaded.
return;
}
setIsProcessing(true);
const { error } = await stripe.confirmPayment({
elements,
confirmParams: {
// Make sure to change this to your payment completion page
return_url: `${window.location.origin}/Completion`,
},
});
if (error.type === "card_error" || error.type === "validation_error") {
setMessage(error.message);
} else {
setMessage("An unexpected error occured.");
}
setIsProcessing(false);
};
return (
<form id="payment-form" onSubmit={handleSubmit}>
<PaymentElement id="payment-element" />
<button
className="rounded-md bg-amber-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-amber-700 mt-4"
disabled={isProcessing || !stripe || !elements}
id="submit"
>
<span id="button-text">
{isProcessing ? "Processing ... " : "Pay now"}
</span>
</button>
{/* Show any error or success messages */}
{message && <div id="payment-message">{message}</div>}
</form>
);
}
this is the entire code.I apologies for the poorly constructed code(am a beginner).
I'm admittedly a bit new to React myself. Quick question, is there a reason that you have {{ clientSecret }} in double curly braces in your Elements initializer?
May be worth trying this again but with a single set of curly braces
Just updated the code, the error is still occuring
let me quicky present you with the updated code and error
Payment.js file ->
import { useEffect, useState } from "react";
import CurrencyChange from "../components/CurrencyChange";
import { Elements } from "@stripe/react-stripe-js";
import CheckoutForm from "./CheckoutForm";
import { loadStripe } from "@stripe/stripe-js";
import { useRouter } from "next/router";
import React from "react";
export default function Payments() {
const router = useRouter();
const { query } = router;
const [costing, setcosting] = useState(null);
const [stripePromise, setstripePromise] = useState(null);
const [clientSecret, setClientSecret] = useState("");
useEffect(() => {
fetch("https://satkarback.onrender.com/config").then(async (r) => {
const { publishableKey } = await r.json();
setstripePromise(loadStripe(publishableKey));
});
}, []);
useEffect(() => {
if (query) {
fetch("https://satkarback.onrender.com/create-payment-intent", {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(query),
})
.then(async (r) => {
if (!r.ok) {
// Added error handling for non-successful responses
throw new Error(`HTTP error! Status: ${r.status}`);
}
const result = await r.json();
const { clientSecret, cost } = result;
setcosting(cost);
setClientSecret(clientSecret);
})
.catch((error) => {
console.error("Error fetching payment intent:", error.message);
// Handle errors as needed
});
}
}, [query]);
return (
<div className="p-14">
{costing && <CurrencyChange ammount={costing} />}
{clientSecret && stripePromise && (
<Elements stripe={stripePromise} options={clientSecret}>
<CheckoutForm props={[query, costing]} />
</Elements>
)}
</div>
);
}
the error -->
Error occurred prerendering page "/CheckoutForm". Read more: https://nextjs.org/docs/messages/prerender-error
Error: Could not find Elements context; You need to wrap the part of your app that calls useStripe() in an <Elements> provider.
at parseElementsContext (/Users/abjeetsingh/Coding/client/node_modules/@stripe/react-stripe-js/dist/react-stripe.js:504:11)
at useElementsOrCustomCheckoutSdkContextWithUseCase (/Users/abjeetsingh/Coding/client/node_modules/@stripe/react-stripe-js/dist/react-stripe.js:486:10)
at useStripe (/Users/abjeetsingh/Coding/client/node_modules/@stripe/react-stripe-js/dist/react-stripe.js:665:31)
at CheckoutForm (/Users/abjeetsingh/Coding/client/.next/server/chunks/383.js:25:86)
at d (/Users/abjeetsingh/Coding/client/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:33:498)
at bb (/Users/abjeetsingh/Coding/client/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:36:16)
at b.render (/Users/abjeetsingh/Coding/client/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:42:43)
at b.read (/Users/abjeetsingh/Coding/client/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:41:83)
at exports.renderToString (/Users/abjeetsingh/Coding/client/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:52:138)
at Object.renderPage (/Users/abjeetsingh/Coding/client/node_modules/next/dist/server/render.js:680:46)
As a quick test, can you try commenting out your useEffect that initializes the stripePromise and just hard code const stripePromise = loadStripe('pk_test_12345'); above your Payments() function?
I'm wondering if the way this is being initialized is effecting it
Your code should wait for it to try to initialize Elements, just trying to rule one more potential issue out
since i am using a useState valriable
setstripePromise(loadStripe("pk_test_12345"));
writting this instead of the suggested
const stripePromise = loadStripe('pk_test_12345');
should i proceed?
Exactly. I don't think that is the cause but just want to double check
this change gives an error
Too many re-renders. React limits the number of renders to prevent an infinite loop.
i guess this is expected as we are not using useeffect for a single render no more
That hardcoded loadStripe should specifically be outside of your Payments() function
Putting it inside the function is expected to do that
Also apologies, my react env is giving me trouble so I haven't been able to test this myself yet
not a problem, am learning a lot with these tests also am grateful to you for assisting me solve this
sure
Also I did realize that your double curly braces around the client secret would be the right thing to pass in. That options prop is expecting an options object with a clientSecret inside of it
yes i corrected that
doing this does not render the payment options without an error(except the already exising one). I guess this was what we were looking for
Double negative is confusing me a bit. The element is no longer rendering at all?
Wait, it already hasn't been rendering. Can you rephrase that last message?
Oh so the error was happening but the element was still showing up?
Do you know if you could submit payments with it?
i guess i wasnt able to phrase my error specifically enough
my code works fine
and everything is completely working as expected
the problem i am having is
when i run NPM RUN BUILD(next BUILD)
as explained here
i want to publish this project on vercel for my client to view it but i is throwing an error during the build
hope this helps to narrow the approach for resolution
Ah, my apologies, I was not reading carefully. I found this StackOverflow where a user also got this issue with Vercel's prerendering. It looks like the two solutions from there were to lazy load the CheckoutForm and disable server-side rendering or the user could have moved their CheckoutForm file from their pages directory to their components directory https://stackoverflow.com/questions/74137681/stripe-elements-despite-wrapping-whole-component-i-getcould-not-find-elements
The following code works fine on localhost. It's just that Vercel's CI/CD throws this error in compilation
Error occurred prerendering page "/billing/CheckoutForm". Read more: https://nex...
Any chance that pages -> components solution could apply to your setup?