#kirito
1 messages · Page 1 of 1 (latest)
Hey there, yes the elements need to be mounted to be referenced. Are you unmounting them?
here is the code I'm using :
const stripe = useStripe();
const elements = useElements();
const [selectedTab, setSelectedTab] = useState('card');
const handleSubmit = async (event) => {
event.preventDefault();const result = await stripe.confirmCardPayment(clientSecret, {
payment_method: {
card: elements.getElement(CardElement),
iban: elements.getElement(IbanElement),
}[selectedTab],
});
if (result.error) {
// Show error to your customer (e.g., insufficient funds)
console.log(result.error.message);
} else {
// The payment has been processed!
if (result.paymentIntent.status === 'succeeded') {
// Show a success message to your customer
console.log('Payment succeeded!');
}
}
};
return (
<form onSubmit={handleSubmit}>
<ChipTabs
selected={selectedTab}
onChange={(tab) => setSelectedTab(tab)}
/>
{selectedTab === 'card' && (
<CardElement options={{ style: { base: { fontSize: '18px' } } }} />
)}
{selectedTab === 'iban' && (
<IbanElement options={{ style: { base: { fontSize: '18px' } } }} />
)}
<button type="submit">Pay</button>
</form>````
depending on the state of selectedTab I'm either showing one or the other but after I switch from one to another and I start typing I got the error
stripe.confirmCardPayment(clientSecret, {
payment_method: {
card: elements.getElement(CardElement),
iban: elements.getElement(IbanElement),
}[selectedTab],
});
Two issues here:
1/ You can't do both card and iban at the same time since one is necessarily unmounted based on your code
2/ confirmCardPayment is only for cards, you can't use iban with that at all
I fixed this issue but still got the same problem
Can you explain more, or show some examples?
Sure
this the code ```export default function PaymentMethodForm({
paymentOptions,
// stripeOptions,
// billingAddress,
className,
}) {
const { t } = useTranslation()
const [ selectedPaymentMethod, setSelectedPaymentMethod ] = useState(1)
const [ isIbanElementValid, setIsIbanElementValid ] = useState(null)
const { setPaymentElementDetails, elements } = paymentOptions
const switchSelectedPaymentMethod = (paymentMethodIndex) => {
setPaymentElementDetails({ isElementValid: false })
setSelectedPaymentMethod(paymentMethodIndex)
}
const ibanElement = elements.getElement(IbanElement)
console.log(isIbanElementValid)
useEffect(() => {
if (ibanElement) {
ibanElement.on("change", (event) => {
setIsIbanElementValid(!event.error && !event.empty)
})
}
return () => {
ibanElement.of("change", (event) => {
setIsIbanElementValid(!event.error || event.empty)
})
}
}, [])
const Input = [
<BankCardForm
key="card-form"
paymentOptions={paymentOptions}
/>,
<IbanElement
key="sepa-form"
options={STRIPE_SEPA_ELEMENT_OPTION}
className={
}
/>,
]
if (!elements) {
return null
}
return (
<PaymentMethodForm.Styled className={className}>
<Chiptabs
scroll={false}
state={[ selectedPaymentMethod, switchSelectedPaymentMethod ]}
>
{PAYMENT_METHOD_IDS.map((paymentMethod, index) => (
<span key={index}>
{t(payment.payment-methods.${PAYMENT_METHODS[paymentMethod]})}
</span>
))}
</Chiptabs>
<Field
as="label"
className="PaymentMethodForm__form"
label={t("payment.inputs.card-infos.label.general")}
>
{Input[selectedPaymentMethod]}
</Field>
</PaymentMethodForm.Styled>
)
}
for the BankCardComponetn ```export default function BankCardForm({ paymentOptions, className }) {
const { t } = useTranslation()
const { setPaymentElementDetails, elements } = paymentOptions
const [ isCardDetailsValid, setIsCardDetailsValid ] = useState({
cardNumber: false,
cardExpiry: false,
cardCvc: false,
})
const handleChange = (event) => {
const isElementValid = !(event.empty || event.error)
// Check if all card elements has valid non-empty data
const isCardFormValid = Object.values({
...isCardDetailsValid,
[event.elementType]: isElementValid,
}).every((item) => item)
setPaymentElementDetails({
paymentData: {
type: PAYMENT_METHODS.bankCard,
// eslint-disable-next-line camelcase
payment_method: { card: elements.getElement(CardNumberElement) },
},
isElementValid: isCardFormValid,
})
// Update the state of the current element
setIsCardDetailsValid((prev) => ({
...prev,
[event.elementType]: isElementValid,
}))
}
if (!elements) {
return null
}
return (
<BankCardForm.Styled className={className}>
<div className="Card__Container">
<div className="Card__Input Card__Input--full-width">
<CardNumberElement
options={STRIPE_ELEMENT_OPTION}
onChange={handleChange}
/>
</div>
<div className="Card__Input Card__Input--half-width">
<CardExpiryElement
options={STRIPE_ELEMENT_OPTION}
onChange={handleChange}
/>
</div>
<div className="Card__Input Card__Input--half-width">
<CardCvcElement
options={STRIPE_ELEMENT_OPTION}
onChange={handleChange}
/>
</div>
</div>
</BankCardForm.Styled>
)
}`````
const paySubscriptionMethod = paymentElementDetails.paymentData.type === PAYMENT_METHODS.SEPA
? "confirmSepaDebitPayment" :
"confirmCardPayment"
console.log({ paymentElementDetails })
try {
if (clientSecret) {
const { error, paymentIntent } = await stripe[paySubscriptionMethod](
clientSecret,
{
payment_method,
},
).catch((error) => {
throw error
})````
the payment method called from the parent component
ok those are fairly large snippets -- what exactly isnt working?
When i switch using the Chiptabs component from element to another and start typing on the input of one of them I get te error I sent above
I’m using conditional rendering
Like { selected === 0 ?<CardElement /> : <IbanElement />}
What part of your code is throwing the error?
The Element
What does that mean?
After changing the value of selected to 1 and I start typing in the IbanElement it throw error
The same for the cardElement
What throws an error?
What error?
You shared this before:
IntegrationError: We could not retrieve data from the specified Element.
What throws this?
We were more asking about what line of code throws that error. Have you debugged to figure out what line that is?