简体   繁体   中英

React JS & Axios Render after getting response data from POST request

How would I go about rendering a component after an axios POST request? I want to load a new component after the success response has been received from Stripe. I am trying to update the state of my component by adding a setState after receiving the response and load a simple div if the state has any values. The issue I am having is that component is not re-rendering when I use the setState.

Below is how I have a stripe component setup and the express server:

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;


Here is my 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 });
      }
    });

  });

this.state.cardListBacklog.length

This is the issue. Its giving 0 before update, and undefined after its updated. Console log and check if its true.

this.state = {
  cardListBacklog: false
};

and

  this.setState({cardListBacklog: true});

should do the trick.

I guess, you expects stripeRes in the state, but you are receiving an object {success: stripeRes} instead.

You response with an object from the server here

res.status(200).send({ success: stripeRes });

But on the client side in the state you expect the array, not an object.

this.state.cardListBacklog.length

Object doesn't have length property by default. You should check something else on the client. Maybe you should update state on success response like

this.setState({cardListBacklog: response.data.success });

This is not super cool, but should give you an idea that client side and server side expect different things.

You should rethink your API.

The idea to use flag of successful response here ( https://stackoverflow.com/a/59011695/10559239 ) makes sense to you, if you doesn't want to use response data in near future. Good as a first step. But the main problem, as I can see is inconsistency between server and client.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM