4

I am trying to display my stripe component, but I am getting this error:

IntegrationError: Only one element of type cardNumber can be created.

I don't know why, since I'm only using it once in my entire app

Any ideas?

This is my index

import ReactDOM from 'react-dom';
import App from './App';

import * as serviceWorker from './serviceWorker';
import { loadStripe } from "@stripe/stripe-js";
import { Elements } from "@stripe/react-stripe-js";
import MyComponent from './components/StripeComponent';


const promise = loadStripe("xxx-xxx-xxx");
ReactDOM.render(
  <React.StrictMode>
      <Elements stripe={promise}>
        <MyComponent/>
      </Elements>
  </React.StrictMode>,
  document.getElementById('root')
);

And this is my component

import React from "react";
import {
  useElements,
} from "@stripe/react-stripe-js";

const MyComponent: React.FC= (props)=>{

  const elements = useElements();


 
    const cardNumberElement = elements?.create('cardNumber', {
      placeholder: ''
    });
    const cardExpiryElement = elements?.create('cardExpiry', {
      placeholder: ''
    });
    const cardCvvElement = elements?.create('cardCvc', {
      placeholder: ''
    });
    
    cardNumberElement?.mount('#card-number-element')
    cardExpiryElement?.mount('#card-expiry-element')
    cardCvvElement?.mount('#card-cvv-element')

 


  const handleSubmit = async (ev: any) => {
    ev.preventDefault();
    

  };
  return (
    <form id="payment-form" onSubmit={handleSubmit}>
      <div id="card-number-element"></div>
      <div id="card-expiry-element"></div>
      <div id="card-cvv-element"></div>
    </form>

  );
}

export default MyComponent
Miguel
  • 119
  • 3
  • 11

3 Answers3

3

Seems it is because you create and mount the card components in the functional component body they are executed on every render of the component, i.e. as an inadvertent side-effect.

Place the creation and mounting logic in an useEffect hook with an empty dependency array so that it is invoked only once when the component mounts.

import React, { useEffect } from "react";
import { useElements } from "@stripe/react-stripe-js";

const MyComponent: React.FC = (props) => {
  const elements = useElements();

  // Effect hook to run once on component mount
  useEffect(() => {
    const cardNumberElement = elements?.create("cardNumber", {
      placeholder: ""
    });
    const cardExpiryElement = elements?.create("cardExpiry", {
      placeholder: ""
    });
    const cardCvvElement = elements?.create("cardCvc", {
      placeholder: ""
    });

    cardNumberElement?.mount("#card-number-element");
    cardExpiryElement?.mount("#card-expiry-element");
    cardCvvElement?.mount("#card-cvv-element");
  }, []); // <-- empty dependency array

  const handleSubmit = async (ev: any) => {
    ev.preventDefault();
  };

  return (
    <form id="payment-form" onSubmit={handleSubmit}>
      <div id="card-number-element"></div>
      <div id="card-expiry-element"></div>
      <div id="card-cvv-element"></div>
    </form>
  );
};
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • Thank you very much, the code worked and I understood the reason why the problem occurred to me – Miguel Aug 28 '20 at 22:29
  • I use initiation in `useEffect` but anyway have the same problem. Could it be because my form is used inside Class component? – David Jan 14 '21 at 16:09
  • @David React hooks are incompatible with class-based components, but perhaps I'm misunderstanding. If you ask a new question here on SO with a [Minimal, Complete, and Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) and clarifying details, feel free to (at) me here with a link to it and I can take a look. – Drew Reese Jan 14 '21 at 16:48
  • it is not a new question. I mean I have form component wich is very similar from this question. And it is stored inside ClassComponent. and each time I opening page with this form, I have an error – David Jan 14 '21 at 17:11
  • @David No worries. Can you share a link to a codesandbox or git repo so I can see the code you're running? I just need a bit more context. I'm inclined to say you *should* ask a new question, and if it turns out it is a duplicate, that's ok, we can just mark it duplicate and close it. If it isn't a duplicate and you've an issue specific to your code, then you'll get more eyes looking at, and hopefully resolving, it more quickly. – Drew Reese Jan 14 '21 at 17:32
  • @DrewReese ok, I created the new question, if you have a chance to look at it, it would be nice. here it is https://stackoverflow.com/questions/65734614/how-to-fix-error-only-one-element-of-type-cardnumber-can-be-created – David Jan 15 '21 at 10:44
1
useEffect(() => {
  if (elements) {
    const cardNumberElement =
      elements.getElement("cardNumber") || // check if we already created element
      elements.create("cardNumber", defaultInputStyles); // create if dont

    cardNumberElement.mount("#numberInput");
  }
}, [elements]);
Behemoth
  • 5,389
  • 4
  • 16
  • 40
Andrii Svirskyi
  • 376
  • 1
  • 4
0

I had the same problem, in my case, I had a reference to CardNumberElement in another section of my code. After removing it, everything worked fine.