【问题标题】:PayPal Smart Payment Buttons using old State使用旧状态的 PayPal 智能支付按钮
【发布时间】:2020-10-16 19:17:05
【问题描述】:

所以场景是我有一个 React + Redux 电子商务商店,并且有一个结帐页面,其中列出了购物车中的所有商品。这很好用,每次我添加产品时按钮都会重新呈现,但是,可以选择从结帐页面上的购物车中删除项目,虽然实际状态发生了变化,但 Paypal 按钮使用旧状态(我假设是因为按钮不会重新渲染)。我已经将按钮包装在一个 useEffect 函数中,该函数应该在每次购物车中的项目发生状态更改时运行,但是,情况并非如此,我就是不知道为什么。

代码如下:

import {useSelector, useDispatch} from 'react-redux'
import {removeProduct} from '../redux/cart/cart.actions'
import './Cart.scss'
import CartItem from '../components/cartComponent/cartItem'


const mapState = ({ cart }) => ({
    itemsInCart: cart.itemsInCart,
    total: cart.total

})

const Cart = props => {

    const [paidFor, setPaidFor] = useState(false);
    const dispatch = useDispatch();
    const {itemsInCart} = useSelector(mapState);
    const {total} = useSelector(mapState);
    let paypalRef = useRef();

    const clickHandler = (e) => {
        e.preventDefault();
        const removeIndex = itemsInCart.findIndex(item => {
           return item.id === e.target.id
    })
        dispatch(removeProduct(removeIndex,itemsInCart[removeIndex]))
    }

        useEffect(() => {
            window.paypal
              .Buttons({
                createOrder: (data, actions) => {
                  return actions.order.create({
                    purchase_units: [
                      {
                        description: "product.description",
                        amount: {
                          currency_code: 'USD',
                          value: total,
                        },
                      },
                    ],
                  });
                },
                onApprove: async (data, actions) => {
                  const order = await actions.order.capture();
                  setPaidFor(true);
                  console.log(order);
                },
                onError: err => {
                  setError(err);
                  console.error(err);
                },
              })
              .render(paypalRef.current);
          },[itemsInCart]);
                
    return (
        <>
        {paidFor ? (
            <div><h1>Congrats you just bought an Article</h1></div>
        ):
        <>
        <h1>Your Shopping Cart</h1>
        <div className = "main">
            <form className="cart-area">
                <ul className="cart-ui">
                     {itemsInCart.map((item, index)=> {
                        return <CartItem
                        clicked={clickHandler}
                        name={item.name}
                        price={item.price}
                        id={item.id}
                        key={index}
                        />
                     })}
                </ul>
 
                <div className="cart-summary">
                    <div className ="cart-wrapper">
                     <div className="name-price-wrapper">
                     <p className="name">Items</p>
                     <p className="price">{total}€</p>
                     </div>
                     <div ref={paypalRef}></div>
                     </div>
                </div>
            </form>
        </div>
        </>
        } 
     </>
    )
}
export default Cart;

当我将 useEffect 挂钩更改为例如总是重新渲染,我多次获得按钮(取决于我删除了多少项目),当单击底部的按钮时,它实际上以正确的数量工作。所以我必须关闭之前的按钮,因为它们会被渲染。

当关注@Preston PHX 的引用帖子时,我的代码如下所示:

useEffect(() => {
          if(window.myButton) window.paypal.close();
          window.myButton = window.paypal
              .Buttons({
                createOrder: (data, actions) => {
                    console.log(total)
                  return actions.order.create({
                    purchase_units: [
                      {
                        description: "product.description",
                        amount: {
                          currency_code: 'USD',
                          value: total,
                        },
                      },
                    ],
                  });
                },
                onApprove: async (data, actions) => {
                  const order = await actions.order.capture();
                  setPaidFor(true);
                  console.log(order);
                },
                onError: err => {
                  setError(err);
                  console.error(err);
                },
              })
              .render(paypalRef.current)

          });

这里我收到错误window.myButton.close() is not a function ...?

【问题讨论】:

    标签: javascript reactjs paypal


    【解决方案1】:

    你误解了useEffect的参数:https://reactjs.org/docs/hooks-effect.html

    这将导致效果只运行如果该参数改变

    它不会导致效果运行无论何时该参数发生变化


    另一个可能的问题是关闭现有按钮,如果您真的要重新渲染它们。如果您的 purchase_units 对象引用了在单击按钮时评估的动态变量/函数,则不需要重新渲染它们。但是,如果您要重新呈现按钮,则可能需要关闭现有按钮。您可以通过在调用 .render 之前存储对 window.PayPal.Buttons(...) 的引用来做到这一点,这样您就可以在第二次调用 .render 之前调用 .close()(如果已定义)。

    如何做到这一点的答案:https://stackoverflow.com/a/62349799/2069605

    【讨论】:

    • 我只是将值更改为 document.getElementById 并创建了对显示当前购物车值的元素的引用。我不明白的是,之前的引用也是来自 redux 钩子 useSelector 的动态...?
    【解决方案2】:
    import React from "react";
    import ReactDOM from "react-dom"
    
    const PayPalButton = paypal.Buttons.driver("react", { React, ReactDOM });
    
    function YourComponent({price}) {
      const createOrder = (data, actions) =>{
        return actions.order.create({
          purchase_units: [
            {
              amount: {
                value: `${price}`,
              },
            },
          ],
        });
      };
    
      const onApprove = (data, actions) => {
        return actions.order.capture();
      };
    
      return (
        <PayPalButton
          createOrder={(data, actions) => createOrder(data, actions)}
          onApprove={(data, actions) => onApprove(data, actions)}
        />
      );
    }
    

    Click here for the Paypal documentation

    或者尝试使用 useRef 挂钩

    import React, { useRef, useEffect } from 'react';
    
    const Paypal = ({ amount }) => {
      const paypal = useRef();
      useEffect(() => {
        if (window.paypalBtn) window.paypalBtn.close();
        window.paypalBtn = window.paypal.Buttons({
          createOrder: function (data, actions) {
            // This function sets up the details of the transaction, including the amount and line item details.
            return actions.order.create({
              purchase_units: [
                {
                  amount: {
                    value: `${amount}`,
                  },
                },
              ],
            });
          },
          onApprove: function (data, actions) {
            // This function captures the funds from the transaction.
            return actions.order.capture().then(function (details) {
              // This function shows a transaction success message to your buyer.
            console.log('details', details);
            alert('Transaction completed by ' + details.payer.name.given_name);
            });
          },
          onError: function (err) {
            console.error(err);
          },
        });
        window.paypalBtn.render(paypal.current);
      }, [amount]);
    
      return (
        <div>
          <div ref={paypal}></div>
        </div>
      );
    };
    
    export default Paypal;
    
    

    【讨论】:

    • 谢谢!在我的应用程序中,我发现 useEffect() 钩子会产生似乎对功能没有影响但在控制台中看起来很难看的错误。驱动程序变体工作得最好,没有错误记录到控制台。再次感谢。
    猜你喜欢
    • 2020-03-23
    • 2019-11-16
    • 2020-05-09
    • 2019-10-31
    • 2021-01-28
    • 2021-05-05
    • 2020-06-09
    • 2020-05-25
    • 2020-11-11
    相关资源
    最近更新 更多