title: Integration of Stripe PaymentElement. Warning Unsupported prop change: options.clientSecret is not a mutable property?
body: <p>I have PaymentMethodPage, which looks like this:</p>
  <pre><code>import React, { FC, useState } from 'react';
  import { Elements } from '@stripe/react-stripe-js';
  import { loadStripe } from '@stripe/stripe-js';
  import {
    getClientSecret,
  } from '../../api/PaymentCalls/PaymentCalls';
  import PaymentMethodSetupForm from './PaymentMethodSetupForm/PaymentMethodSetupForm';
  import AddPaymentMethodContainer from './AddPaymentMethodContainer/AddPaymentMethodContainer';
  import {
    ClientSecretResponse,
  } from '../../interfaces/paymentMethod.interface';
  
  
  const stripePromise = loadStripe(
    process.env.REACT_APP_STRIPE_PUBLIC_KEY as string
  );
  
  const PaymentMethodPage: FC = () =&gt; {
    const [enableAddPaymentMethod, setEnableAddPaymentMethod] =
      useState&lt;boolean&gt;(false);
  
    const {
      data: clientSecretKeyData,
    }: UseQueryResult&lt;ClientSecretResponse, ExtendedError&gt; = useQuery&lt;
      ClientSecretResponse,
      ExtendedError
    &gt;('getClientSecret', getClientSecret, {
      retry: false,
      refetchOnWindowFocus: false,
      enabled: enableAddPaymentMethod,
      onError: (error: ExtendedError) =&gt; {
        if (error) {
          console.log(error)
        }
      },
    });
  
    const options = {
      clientSecret: clientSecretKeyData?.client_secret,
    };
  
    const addPaymentMethodHandler = (): void =&gt; {
      setEnableAddPaymentMethod(!enableAddPaymentMethod);
    };
  
    
    return (
      &lt;AppDrawer onLogOut={logoutHandler}&gt;
  
            {paymentMethodData.default_payment_method !== null ? (
              &lt;Box&gt;
                &lt;Typography&gt;
                  Payment Method
                &lt;/Typography&gt;
              &lt;/Box&gt;
            ) : (
              &lt;Box&gt;
                &lt;AddPaymentMethodContainer
                  addButtonHandler={addPaymentMethodHandler}
                /&gt;
              &lt;/Box&gt;
              {clientSecretKeyData &amp;&amp; (
                &lt;Elements stripe={stripePromise} options={options}&gt;
                  &lt;PaymentMethodSetupForm
                    isOpenPaymentDialog={enableAddPaymentMethod}
                    handleClose={addPaymentMethodHandler}
                    setPaymentDialogOpen={addPaymentMethodHandler}
                  /&gt;
                &lt;/Elements&gt;
              )}
      &lt;/AppDrawer&gt;
    );
  };
  
  export default PaymentMethodPage;
  
  </code></pre>
  <p>If there is no payment method I am rendering AddPaymentMethodContainer.
  Which looks like this:</p>
  <pre><code>import React, { FC } from 'react';
  import { Box, Typography, Button } from '@mui/material';
  
  interface AddPaymentMethodContainerProps {
    addButtonHandler: () =&gt; void;
  }
  
  const AddPaymentMethodContainer: FC&lt;AddPaymentMethodContainerProps&gt; = ({
    addButtonHandler,
  }) =&gt; {
    return (
      &lt;Box &gt;
        &lt;Box &gt;
          &lt;img
            src={someImage}
            alt=&quot;no-payment-method&quot;
          /&gt;
        &lt;/Box&gt;
        &lt;Typography&gt;
          No payment method found. Click the button below to provide one.
        &lt;/Typography&gt;
        &lt;Box sx={styles.addButtonContainer}&gt;
          &lt;Button
            sx={styles.addButton}
            variant=&quot;contained&quot;
            onClick={addButtonHandler}
          &gt;
            Add Payment
          &lt;/Button&gt;
        &lt;/Box&gt;
      &lt;/Box&gt;
    );
  };
  
  export default AddPaymentMethodContainer;
  
  </code></pre>
  <p>Once the add button is clicked I am rendering the payment form, which contains Stipe PaymentElement...
  The component looks like this:</p>
  <pre><code>import React, { FC, useState } from 'react';
  import {
    PaymentElement,
    useStripe,
    useElements,
  } from '@stripe/react-stripe-js';
  import { useMutation, UseMutationResult, useQueryClient } from 'react-query';
  import { Dialog, DialogTitle, DialogContent } from '@mui/material';
  
  interface PaymentMethodSetupFormProps {
    isOpenPaymentDialog: boolean;
    handleClose: () =&gt; void;
    setPaymentDialogOpen: (e: boolean) =&gt; void;
  }
  
  const PaymentMethodSetupForm: FC&lt;PaymentMethodSetupFormProps&gt; = ({
    isOpenPaymentDialog,
    setPaymentDialogOpen,
    handleClose,
  }) =&gt; {
    const stripe = useStripe();
    const elements = useElements();
    const [isLoading, setIsLoading] = useState&lt;boolean&gt;(false);
  
  
    // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
    const handleSubmit = async (event: React.SyntheticEvent) =&gt; {
      event.preventDefault();
  
      if (!stripe || !elements) {
        // eslint-disable-next-line no-useless-return
        return;
      }
      setIsLoading(true);
  
      const result = await stripe.confirmSetup({
        elements,
        confirmParams: {
          return_url: 'http://localhost:3000/payment-status/',
        },
        redirect: 'if_required',
      });
  
      if (result.error) {
        console.log(`${result.error.message}`)
      } else {
        console.log('All okay!')
        setPaymentDialogOpen(false);
      }
  
      setIsLoading(false);
    };
  
    return (
      &lt;Dialog
        open={isOpenPaymentDialog}
        onClose={handleClose}
      &gt;
        &lt;DialogTitle&gt;
          Payment Methods:
        &lt;/DialogTitle&gt;
        &lt;DialogContent&gt;
          &lt;form onSubmit={handleSubmit}&gt;
            &lt;PaymentElement /&gt;
            &lt;CustomSubmitButton
              cypressId=&quot;credit-card-submit-button&quot;
              isLoading={isLoading}
              text=&quot;Save&quot;
              style={{ margin: '2rem auto', fontWeight: 'bolder' }}
              disabled={isLoading}
            /&gt;
          &lt;/form&gt;
        &lt;/DialogContent&gt;
      &lt;/Dialog&gt;
    );
  };
  
  export default PaymentMethodSetupForm;
  
  </code></pre>
  <p>Here I am disabling the function return type of handleSubmit, because I don't know what should be the type... It is a Promise&lt;&gt;, so If anyone has any idea(please help).
  In general, all is working fine, what I do not like is when I click &quot;ADD&quot; button to open the form and I close it, on the second attempt when the button is pressed, there is a warning in the console:</p>
  <pre><code>Unsupported prop change: options.clientSecret is not a mutable property.
  </code></pre>
  <p>As well there is a warning regarding the images inside the PaymentElement ( for the card number ) :</p>
  <pre><code>Each dictionary in the list &quot;icons&quot; should contain a non-empty UTF8 string field &quot;type&quot;.
  </code></pre>
  <p>And the last thing, which is very annoying. As per their documentation, I can disable the submit/save/pay button in the form like this:</p>
  <pre><code>return (
      &lt;form onSubmit={handleSubmit}&gt;
        &lt;PaymentElement /&gt;
        &lt;button disabled={!stripe}&gt;Submit&lt;/button&gt;
        {/* Show error message to your customers */}
        {errorMessage &amp;&amp; &lt;div&gt;{errorMessage}&lt;/div&gt;}
      &lt;/form&gt;
    )
  
  </code></pre>
  <p>But it looks like this object is always truty. I tried to make it like this:</p>
  <pre><code>return (
      &lt;form onSubmit={handleSubmit}&gt;
       {!stripe &amp;&amp; (
        &lt;PaymentElement /&gt;
        &lt;button&gt;Submit&lt;/button&gt;
        {/* Show error message to your customers */}
        {errorMessage &amp;&amp; &lt;div&gt;{errorMessage}&lt;/div&gt;}
        )}
      &lt;/form&gt;
    )
  </code></pre>
  <p>Because why should I disable it when I could just render it when the stripe is available.
  But looks like it is not working like that. The submit button is always there, and suddenly the payment form appears... Which is not so nice. As a user, I got a button and at some time the form shows up. Okay, it does not take so much time, but in my opinion, it is not cool.</p>