简体   繁体   English

React-在获取数据后设置状态时渲染HTML

[英]React - Render HTML When Setting a State After Fetching Data

I have an application which needs to fetch invoice data from Stripe API (payment processor). 我有一个需要从Stripe API(付款处理器)中提取发票数据的应用程序。 When the invoice data has been returned, I'm trying to update my state using this.setState({invoiceData: invoices}) where invoices is a string of HTML that I build out from the data returned from the Stripe API. 返回发票数据后,我正在尝试使用this.setState({invoiceData: invoices})更新状态,其中invoices是从Stripe API返回的数据中构建的HTML字符串。

The issue is that the HTML isn't being rendered and is showing as plain text. 问题在于HTML无法呈现,而是显示为纯文本。 I am pretty new to React and have only just got my head around rendering states, but now I'm pretty stuck on working this one out. 我对React很陌生,只是对渲染状态一无所知,但是现在我很想解决这个问题。 What do I need to do to render the HTML? 我需要做什么来呈现HTML? Please see my code below. 请在下面查看我的代码。

import React from 'react';

class BillingInvoices extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            invoiceData: false
        }
    }

    // When the 'BillingInvoices' component is mounted:
    componentDidMount() {

        // Get invoice data from Stripe API.
        fetch('/stripe-invoices', {
            method: 'POST',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                customerId: '128973982'
            })
        })
        .then((response) => {
            if (response.ok) {
                return response.json();
            } else {
                console.log('Error with Stripe response');
            }
        })
        .then((stripeData) => {

            var invoiceCount = stripeData['result']['data'].length;
            var i;
            var invoices = '';

            for (i = 0; i < invoiceCount; i++) {
                invoices += '<div><a href="' + stripeData['result']['data'][i]['invoice_pdf'] + '" download>' + stripeData['result']['data'][i]['number'] + '</a></div>';
            }

            this.setState({
                invoiceData: invoices
            })
        })
        .catch((error) => {
            console.log('Error: ', error);
        });
    }

    render() {
        return (
            <div id="billing-invoices">
                {this.state.invoiceData ? this.state.invoiceData : null}
            </div>
        );
    }
}

export default BillingInvoices;

Thank you for any insight. 感谢您的见解。

You can populate invoiceData with react components using JSX like so: 您可以使用JSX使用反应组件填充invoiceData ,如下所示:

let invoices = (<div>{stripeData['result']['data'].map(data => (<div><a href={data['invoice_pdf']}  download>{data['number']}</a></div>))}</div>);

this.setState({invoiceData: invoices});

You can replace the content of the second then clause with the above and leave the rest of the code unchanged. 您可以使用上述内容替换第二个then子句的内容,并使其余代码保持不变。

I've stripped out some of your code for my example to make it easier to read: 我为示例删除了一些代码,以使其更易于阅读:

class BillingInvoices extends React.Component {

  constructor(props) {
    super(props);
    this.state = { invoiceData: [] }
  }

  componentDidMount() {
    fetch('/stripe-invoices')
      .then((response) => response.ok && response.json())

      // Here I'm assigning the nested array to `invoiceData` immediately
      // so that you don't need to map over it later
      .then((data) => this.setState({ invoiceData:  data.result.data }));
  }

  render() {

    // Here we can check if the data exists. If it doesn't
    // show a loading icon (or something) until it is
    if (!this.state.invoiceData) <Loader />

    // ...otherwise show the data
    return (
      <div id="billing-invoices">

        // we map over the invoice data and for each invoice
        // return JSX (your div with an anchor populated with that invoice data)
        {this.state.invoiceData.map((invoice) => {
          return (
            <div>
              <a href={invoice.invoice_pdf} download>{invoice.number}</a>
            </div>
          )
        })}
      );
      </div>
    )
  }
}

Putting the resulted json in the component state is a good idea. 将结果json置于组件状态是一个好主意。

But then, you should deal with this json directly in your render method, using the power of JSX. 但是,然后,您应该使用JSX的功能直接在渲染方法中处理此json。

Check the official documentation about how to use JSX. 查看有关如何使用JSX的官方文档

This is a dummy example of what your component could look like with the usage of JSX: 这是一个使用JSX时您的组件看起来像的虚拟示例:

import React from "react";

class BillingInvoices extends React.Component {
  constructor(props) {
    super(props);
  }

  state = {
    invoices: []
  }

  // When the 'BillingInvoices' component is mounted:
  componentDidMount() {
    // Get invoice data from Stripe API.
    fetch("/stripe-invoices", {
      method: "POST",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        customerId: "128973982"
      })
    })
      .then(response => {
        if (response.ok) {
          this.setState(invoices: response.json());
        } else {
          console.log("Error with Stripe response");
        }
      })
      .catch(error => {
        console.log("Error: ", error);
      });
  }

  render() {
    return (
      <div id="billing-invoices">
        {this.state.invoices.map((invoice, index) => {
          return (
            <div key={index}>{invoice.name}</div>
          )
        })}
      </div>
    );
  }
}

export default BillingInvoices;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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