使用React的Promises时的实现问题

问题描述

我正在做一个需要实施订单管理系统的任务。问题是我需要进行GET调用才能获取所有订单,并且对于每个订单,我都需要进行另一个GET调用,以便可以获取此订单的商品。 我的问题是,在呈现所有内容之前,如何进行这些调用并创建订单和项目的某些数据结构。 我尝试使用async / await,但在呈现所有内容之前无法创建订单及其相关项目的数据结构。

目前,我只处理GET呼叫的订单

async componentDidMount() {
        const orders = await api.getorders()
        this.setState({
            orders
        });
    }

我还为商品的GET调用创建了一个函数,该函数返回Promise

createItemsList = (order: Order) => {
        let a = order.items.map((item) => {
            return api.getItem(item.id);
        });
        return Promise.all(a);
    };

有人建议将两者结合起来吗?预先感谢!

***编辑*** 这是我渲染订单的代码的一部分

{filteredOrders.map((order) => (
                    <div className={'orderCard'}>
                        <div className={'generalData'}>
                            <h6>{order.id}</h6>
                            <h4>{order.customer.name}</h4>
                            <h5>Order Placed: {new Date(order.createdDate).toLocaleDateString()},At: {new Date(order.createdDate).toLocaleTimeString()}</h5>
                        </div>
                        <Fulfilment order={order}/>
                        <div className={'paymentData'}>
                            <h4>{order.price.formattedTotalPrice}</h4>
                            <img src={App.getAssetByStatus(order.billingInfo.status)}/>
                        </div>
                        <ItemsList subItemsList={order.items} api={api}/>
                    </div>
                ))}

在组件ItemsList中,我呈现特定订单的商品,而order.items不是商品本身,而是我在每个订单中获得的商品ID和数量的数组

解决方法

我建议您将数据检索移到每个组件中。

检查sandbox here

import React,{ PureComponent } from "react";


const fakeOrderItems = {
  1: [
    {
      id: 1,name: "Ramen",qty: 1
    },{
      id: 1,name: "Beer",qty: 1
    }
  ],2: [
    {
      id: 1,name: "Steak",{
      id: 2,name: "Iced Tea",qty: 1
    }
  ]
};

const fakeOrders = [
  {
    id: 1,name: "Table 1",totalItems: 2
  },{
    id: 2,name: "Table 3",totalItems: 2
  }
];

const fakeApi = {
  getOrders() {
    return new Promise((resolve) =>
      setTimeout(() => resolve(fakeOrders),3000)
    );
  },getOrderItems(id) {
    return new Promise((resolve) =>
      setTimeout(() => resolve(fakeOrderItems[id]),3000)
    );
  }
};

class OrderItem extends PureComponent {
  render() {
    const { id,name,qty } = this.props;

    return (
      <div style={{ marginBottom: 10 }}>
        <span>
          {id}. {name} qty:{qty}
        </span>
      </div>
    );
  }
}

class OrderItemList extends PureComponent {
  state = {
    orderItems: []
  };

  componentDidMount() {
    fakeApi
      .getOrderItems(this.props.orderId)
      .then((orderItems) => this.setState({ orderItems }));
  }

  render() {
    const { orderItems } = this.state;

    if (!orderItems.length) {
      return <span>Loading orderItems...</span>;
    }

    return orderItems.map((item) => (
      <OrderItem key={item.id + item.name} {...item} />
    ));
  }
}

class Order extends PureComponent {
  render() {
    const { id,name } = this.props;
    return (
      <div style={{ marginBottom: 10 }}>
        <div>
          <span>Order #{id}</span>
        </div>
        <div>
          <span>For table {name}</span>
        </div>
        <OrderItemList orderId={id} />
      </div>
    );
  }
}

class OrderList extends PureComponent {
  state = {
    orders: []
  };

  componentDidMount() {
    fakeApi.getOrders().then((orders) => this.setState({ orders }));
  }

  render() {
    const { orders } = this.state;

    if (!orders.length) {
      return <div>Loading orders...</div>;
    }

    return orders.map((order) => <Order key={order.id} {...order} />);
  }
}

export default function App() {
  return <OrderList />;
}

,

您可以尝试此解决方案。几天前我也遇到了同样的问题。所以它的作用是在运行createItemsList函数后setState呈现

async componentDidMount() {
            const orders = await api.getOrders()
            this.setState({
                orders
            }),() => this.createItemsList()
    }
,

在外部创建一个单独的方法来获取所需的数据。

首先从API获取订单。然后遍历每个订单,并再次为每个项目调用api。等待Promise.all等待顺序完成每个项目,然后将结果连接到一个数组,在其中存储所有提取的项目。然后,在循环完成之后,返回结果数组。

在您的componentDidMount中调用此方法,并根据承诺返回的结果更新状态。

state = {
    orders: []
}

async getOrderItems() {
    let orderItems = [];
    const orders = await api.getOrders()
    for (const order of orders) {
        const items = await Promise.all(
            order.items.map((item) => api.getItem(item.id))
        )
        orderItems = [...orderItems,...items]
    }
    return orderItems
}

componentDidMount() {
    this.getOrderItems().then(orders => {
        this.setState({
            orders
        })
    })
}

render() {
    if (this.state.orders.length === 0) {
        return null
    }

    return (
        {this.state.orders.map(order => (
            // Render content.
        )}
    )
}