使用旧状态的 PayPal 智能支付按钮
Posted
技术标签:
【中文标题】使用旧状态的 PayPal 智能支付按钮【英文标题】:PayPal Smart Payment Buttons using old State 【发布时间】: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
...?
【问题讨论】:
【参考方案1】:你误解了useEffect的参数:https://reactjs.org/docs/hooks-effect.html
这将导致效果只运行如果该参数改变
它不会导致效果运行无论何时该参数发生变化
另一个可能的问题是关闭现有按钮,如果您真的要重新渲染它们。如果您的 purchase_units 对象引用了在单击按钮时评估的动态变量/函数,则不需要重新渲染它们。但是,如果您要重新呈现按钮,则可能需要关闭现有按钮。您可以通过在调用 .render 之前存储对 window.PayPal.Buttons(...) 的引用来做到这一点,这样您就可以在第二次调用 .render 之前调用 .close()(如果已定义)。
如何做到这一点的答案:https://***.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()
钩子会产生似乎对功能没有影响但在控制台中看起来很难看的错误。驱动程序变体工作得最好,没有错误记录到控制台。再次感谢。以上是关于使用旧状态的 PayPal 智能支付按钮的主要内容,如果未能解决你的问题,请参考以下文章