我使用的是react-paypal-js,需要在单击PayPal按钮时设置一个动态数量。
问题:createOrder函数不能从我的状态获取数据(可能是因为它在PayPal脚本上下文下)。
不工作的示例:
const [amount, setAmount] = useState('');
const handleCreatePaypal = (data, actions) => {
const orderAmount = parseFloat(amount).toFixed(2) || '1.00'; //amount is the state
console.log(amount, orderAmount)
return actions.order.create({
purchase_units: [
{ amount: { value: orderAmount } }
]
})
}
return (
<PayPalScriptProvider options={paypalOptions}>
<PayPalButtons
createOrder={(data, actions) => handleCreatePaypal(data, actions)}
onApprove={(data, actions) => handlePaypalApprove(data, actions)}
onError={handlePaymentError}
/>
</PayPalScriptProvider>
)不完美解决方案:
const amountRef = useRef(null); //ref on input not showing here
...
const orderAmount = parseFloat(amountRef.current.value).toFixed(2) || '1.00'; //get value from html
... <PayPalScriptProvider options={paypalOptions}>
<PayPalButtons
createOrder={(data, actions) => handleCreatePaypal(data, actions)}
forceReRender={[amount]} //force re-render when amount changes
/>
</PayPalScriptProvider>有解决这个问题的办法吗?提前感谢!
如果没有解决方案,我可能需要从后端进行集成:
我不想这太复杂,因为它只是一个简单的捐赠按钮。
发布于 2021-09-21 08:33:03
从后端集成通常是最健壮的解决方案,尤其是对于电子商务--但由于这是一个简单的捐赠用例,我可以看到您可能希望避免这种情况。
有各种可能的解决方案,包括使用其他状态框架(如Redux ),但您似乎要做的是在按钮之上的父组件级别管理状态,以及bind its createOrder ("handleCreatePayPal")方法等,以便this处于上下文中,并且它们可以访问其状态。
下面是一个可运行的代码框示例 (基于使用重呈现的文档示例。,但这里没有完成)
import { PayPalScriptProvider, PayPalButtons } from "@paypal/react-paypal-js";
import * as React from "react";
const debug = true;
const initialState = {
amount: "2.00",
orderID: "",
onApproveMessage: "",
onErrorMessage: ""
};
export default class App extends React.Component<{}, typeof initialState> {
constructor(props: any) {
super(props);
this.state = initialState;
this.onChange = this.onChange.bind(this);
this.createOrder = this.createOrder.bind(this);
this.onApprove = this.onApprove.bind(this);
this.onError = this.onError.bind(this);
this.onClick = this.onClick.bind(this);
}
onChange(event: React.ChangeEvent<HTMLSelectElement>) {
this.setState({
amount: event.target.value,
orderID: "",
onApproveMessage: "",
onErrorMessage: ""
});
}
createOrder(data: Record<string, unknown>, actions: any) {
if (debug) console.log("Creating order for amount", this.state.amount);
return actions.order
.create({
purchase_units: [
{
amount: {
value: this.state.amount
}
}
]
})
.then((orderID: any) => {
this.setState({ orderID: orderID });
return orderID;
});
}
onApprove(data: any, actions: any) {
let app = this;
return actions.order.capture().then(function (details: any) {
app.setState({
onApproveMessage: `Transaction completed by ${details.payer.name.given_name}!`
});
});
}
onError(err: Record<string, unknown>) {
this.setState({
onErrorMessage: err.toString()
});
}
onClick() {
if (debug) console.log("When clicked, amount was", this.state.amount);
}
render() {
return (
<div style={{ minHeight: "300px" }}>
<table className="table" style={{ maxWidth: "400px" }}>
<tbody>
<tr>
<th>
<label htmlFor="amount">Order Amount: </label>
</th>
<td>
<select onChange={this.onChange} name="amount" id="amount">
<option value="2.00">$2.00</option>
<option value="4.00">$4.00</option>
<option value="6.00">$6.00</option>
</select>
</td>
</tr>
<tr>
<th>Order ID:</th>
<td>{this.state.orderID ? this.state.orderID : "unknown"}</td>
</tr>
<tr>
<th>On Approve Message: </th>
<td data-testid="message">{this.state.onApproveMessage}</td>
</tr>
<tr>
<th>On Error Message: </th>
<td data-testid="error">{this.state.onErrorMessage}</td>
</tr>
</tbody>
</table>
<PayPalScriptProvider options={{ "client-id": "test" }}>
<PayPalButtons
createOrder={this.createOrder}
onApprove={this.onApprove}
onError={this.onError}
onClick={this.onClick}
/>
</PayPalScriptProvider>
</div>
);
}
}https://stackoverflow.com/questions/69259922
复制相似问题