I get the error : - Unhandled Rejection (TypeError): Cannot read property 'id' of undefined in React Application

泪湿孤枕 提交于 2021-01-07 06:35:25

问题


My Payment.js :-

import React, { useState, useEffect } from 'react'
import "./Payment.css"
import { useStateValue } from './StateProvider'
import CheckoutProduct from './CheckoutProduct';
import { Link, useHistory } from 'react-router-dom';
import { CardElement,useElements, useStripe } from '@stripe/react-stripe-js';
import CurrencyFormat from 'react-currency-format';
import { getBasketTotal } from './reducer';
import axios from "./axios";
import {db} from "./firebase";

function Payment() {
    const [{basket, user}, dispatch] = useStateValue();
    const history = useHistory();

    const stripe = useStripe();
    const elements = useElements();

    const [succeeded, setSucceeded]=useState(false);
    const [processing,setProcessing] = useState(""); 
    const [error, setError] = useState(null);
    const [disabled, setDisabled] =useState(true);
    const [clientSecret, setClientSecret] =useState(true);
    
    useEffect(() =>{
        //generate the special stripe secret which allows us to charge the customer

        const getClientSecret = async () => {
            const response = await axios({
                method: 'Post',
                // Stripe expects the total in a currencies submits
                url: `/payments/create?total=${getBasketTotal(basket) * 100}`
            });
            setClientSecret(response.data.clientSecret)
        }
        
        getClientSecret();
    },[basket])

console.log("THE SCRET KEY IS >>>>>", clientSecret)
console.log("Hey! I am the user: My props", user);

    const handleSubmit = async (event) =>{
        // do all the fancy stripe stuff 
        event.preventDefault();
        setProcessing(true);
        
        const payload = await stripe.confirmCardPayment(clientSecret, {
            payment_method: {
                card: elements.getElement(CardElement)
            }
        }).then(({paymentIntent})=>{
            
            db.collection('users').doc(user?.uid).collection('orders').doc(paymentIntent.id).set({basket: basket,amount: paymentIntent.amount,created: paymentIntent.created})

            setSucceeded(true);
            setError(null);
            setProcessing(false)

            dispatch({
                type: 'EMPTY_BASKET'
            })
            history.replace('/orders')
        })
    }

    const handleChange = event =>{
        //handle for changes in tht CardElement
        // and display any error as the customer types their card details
        setDisabled(event.empty);
        setError(event.error ? event.error.message : "")
    }

    return (
        <div className="payment">
            <div className="payment__container">
            <h1>
                Checkout Products(
                {<Link to="/checkout">{basket?.length} items
                </Link>})
            </h1>

             {/* payment section-delivery address  */}
                <div className="payment__section">
                    <div className="payment__title">
                            <h3>Delivery Address</h3>
                    </div>
                    <div className="payment__address" >
                        <p>{user?.email}</p> 
                        <p>123 React Lane</p> 
                        <p>Los Angeles, CA</p> 
                    </div>
                </div>  
              {/* payment section-delivery address   */}
              <div className="payment__section">
                    <div className="payment__title">
                        <h3>Review items and delivery</h3>
                    </div>
                    <div className="payment__items">
                        {basket.map( item =>
                            <CheckoutProduct
                                id={item.id}
                                title={item.title}
                                image={item.image}
                                price={item.price}
                                rating={item.rating}  />
                                 )}
                    </div>
                </div>
              {/* payment section-delivery address   */}
              <div className="payment__section paymentBox">
                  <div className="payment__title">
                      <h3>Payment Method</h3>
                  </div>
                  <div className="payment__details">
                      {/* stripe magic will goes here */}
                  
                            <form onSubmit={handleSubmit} >
                                <CardElement  onChange={handleChange}/>

                                <div className="payment__priceContainer">
                                    <CurrencyFormat
                                     renderText={(value)=>(
                                     <h3>Order total {value}</h3>
                                     )}
                                     decimalScale={2}
                                     value={getBasketTotal(basket)}
                                     displayType={"text"}
                                     thousandSeparator={true}
                                     prefix={"₹"}
                                    />
                                    <button disabled={processing || disabled || succeeded}>
                                        <span>{processing?<p>processing</p>:"Buy Now"}</span>
                                    </button>                                                     
                               </div>

                               {/* Error */}
                               {error && <div>{error}</div>}
                            </form>
                  </div>  
               </div>
            </div>
        </div>
    )
}
export default Payment;

And the error is here :-

const handleSubmit = async (event) =>{
    // do all the fancy stripe stuff 
    event.preventDefault();
    setProcessing(true);
const payload = await stripe.confirmCardPayment(clientSecret, {
    payment_method: {
        card: elements.getElement(CardElement)
    }
}).then(({paymentIntent})=>{

    db.collection('users').doc(user?.uid).collection('orders').doc(paymentIntent.id).set({basket: basket,amount: paymentIntent.amount,created: paymentIntent.created})

    setSucceeded(true);
    setError(null);
    setProcessing(false)

    dispatch({
        type: 'EMPTY_BASKET'
    })
    history.replace('/orders')
})

}

Now, I can understand that it means to say that paymentIntent is undefined but why is it undefined? I tried doing console.log(paymentIntent) inside this function and it said that paymentIntent is undefined.

I have checked for all spelling errors and firebase config.js too.

My application doesn't make the collections in The Firebase neither does it replace the page from /payment to /orders.

I made this app again from scratch and yet the same error occurs. I tried to change my Firebase and Stripe accounts yet I get this error.

Please tell how to fix this error. If you need any other file, I will send you.


回答1:


According to stripe docs.

paymentIntent is only present when the request is successful. Instead of destructuring directly, Could you also check the errors object associated with it. And access paymentIntent only if there are no errors present.

I suggest you log the entire result object first and check what is happening.




回答2:


The confirmCardPayment method in Stripe.js does not return a Payment Intent, it returns a result object. In your return handler you should first check for result.error and, if that's present, handle it. Otherwise you can access result.paymentMethod (or result.paymentMethod.id).

Have a look at this sample code from the Stripe.js reference:

stripe.confirmCardPayment('{PAYMENT_INTENT_CLIENT_SECRET}', {
    payment_method: {
      card: cardElement,
      billing_details: {
        name: 'Jenny Rosen',
      },
    },
  })
  .then(function(result) {
    // Handle result.error or result.paymentIntent
  });

You don't have error handling and you're not looking for the Payment Intent ID in the right place, which is why you're getting the "Unhandled Rejection (TypeError): Cannot read property 'id' of undefined in React Application" error.




回答3:


The error is (message: "As per Indian regulations, export transactions require a description. More info here: https://stripe.com/docs/india-exports) in my case....

so the confirmCardPayment method does not return a Payment Intent../

And solution is change currency from 'USD' to other currency like 'INR' in (functions/index.js)

amount : total, currency : 'INR'



来源:https://stackoverflow.com/questions/65318451/i-get-the-error-unhandled-rejection-typeerror-cannot-read-property-id-o

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!