在axios POST请求后如何呈现组件?在收到Stripe的成功响应后,我想加载一个新组件。我试图通过在收到响应后添加setState来更新组件的状态,如果状态具有任何值,则加载一个简单的div。我遇到的问题是,当我使用setState时,该组件未重新渲染。
下面是我如何配置条带组件和Express服务器:
import StripeCheckout from 'react-stripe-checkout';
import axios from 'axios';
import './stripe-button.styles.scss';
import { createStructuredSelector } from 'reselect';
import { selectCurrentUser } from '../../redux/user/user.selectors';
import { setCurrentUser } from '../../redux/user/user.actions';
class StripeCheckoutButton extends React.Component {
constructor(props) {
super(props);
this.state = {
cardListBacklog: []
};
}
onToken = token => {
console.log(token);
const { cartItems, price } = this.props;
const priceForStripe = price * 100;
const orderSummary = cartItems.reduce(
(cartItemAll, cartItem) =>
(cartItemAll += cartItem.name + cartItem.quantity),
''
);
axios({
url: 'payment',
method: 'post',
data: {
amount: priceForStripe,
order: orderSummary,
token
}
})
.then(response => {
alert(
`Payment successful, ${response.data.success.billing_details.name}; please check your email for your receipt.`
);
this.setState({cardListBacklog: response.data});
})
.catch(error => {
console.log('Payment error: ', JSON.parse(error));
alert('There was an issue with your payment. Please try again!');
});
};
render() {
const publishableKey = 'pk_test_gxxxxxxxxxxxxxxxxxxxxxxxxxxx';
const { price } = this.props;
const priceForStripe = price * 100;
return (
this.state.cardListBacklog.length
?
<div>Payment Successful</div>
:
<StripeCheckout
label="Pay Now"
name="Ltd."
billingAddress
shippingAddress
image="https://i.imgur.com/vWgUzv.png"
description={`Your total is $${price} USD`}
amount={priceForStripe}
panelLabel="Pay Now"
token={this.onToken}
stripeKey={publishableKey}
label="Pay with ?"
/>
);
}
}
export default StripeCheckoutButton;
这是我的Server.js:
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const path = require('path');
if (process.env.NODE_ENV !== 'production') require('dotenv').config();
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const app = express();
const port = process.env.PORT || 5000;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cors());
if (process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, 'client/build')));
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname, 'client/build', 'index.html'));
});
}
app.listen(port, error => {
if (error) throw error;
console.log('Server running on port: ' + port);
});
app.post('/payment', (req, res) => {
const body = {
source: req.body.token.id,
amount: req.body.amount,
receipt_email: req.body.token.email,
description: req.body.order,
currency: 'usd'
};
stripe.charges.create(body, (stripeErr, stripeRes) => {
if (stripeErr) {
res.status(500).send({ error: stripeErr });
} else {
res.status(200).send({ success: stripeRes });
}
});
});
答案 0 :(得分:2)
this.state.cardListBacklog.length
这是问题。它在更新前给0,在更新后给undefined。控制台日志,并检查其是否为真。
this.state = {
cardListBacklog: false
};
和
this.setState({cardListBacklog: true});
应该可以解决问题。
答案 1 :(得分:0)
我想,您希望stripeRes
处于该状态,但是您正在接收一个对象
改为{success: stripeRes}
。
您在此处使用服务器中的对象作为响应
res.status(200).send({ success: stripeRes });
但是在客户端state
中,您期望数组而不是对象。
this.state.cardListBacklog.length
默认情况下,对象没有length
属性。
您应该检查客户端上的其他内容。也许你应该更新状态
像
this.setState({cardListBacklog: response.data.success });
这不是很酷,但是应该让您知道客户端和服务器端期望的是不同的东西。
您应该重新考虑您的API。
如果您不希望在不久的将来使用响应数据,则在此处使用成功响应标志(https://stackoverflow.com/a/59011695/10559239)的想法对您来说很有意义。第一步很好。 但是,我看到的主要问题是服务器和客户端之间的不一致。