2

I'm new to flutter and amplify. I'm trying to do an app using flutter and amplify as backend. I want to retrieve data from three datastore table at once and put them in to a List<Map<String, dynamic>>. I can read data from the List but the data display only when I press refresh or hot reload. I think maybe the mistake is the way I put the setstate? Could anyone tell me what I did wrong? Any help would be much appreciated!

Here is my code

  late StreamSubscription _subscription;
  List<Map<String, dynamic>> _orderList = [];

  @override
  void initState() {
    super.initState();
    _subscription =
        Amplify.DataStore.observe(OrderItem.classType).listen((event) {
      _fetchOrder();
    });
    _orderList = [];
    _fetchOrder();
  }

 Future _fetchOrder() async {

    List<Map<String, dynamic>> fullOrderItemList = [];

    // fetch all order by user id
    final user = await Amplify.Auth.getCurrentUser();
    List<Order> orderDb = await Amplify.DataStore.query(Order.classType,
        where: Order.USERID.eq(user.userId));

    // fetch order item and user name by order id & user id
    orderDb.asMap().forEach((index, order) async {
      List<Map<String, String>> orderItemByOrderId = [];

      User buyerInfo = (await Amplify.DataStore.query(User.classType,
          where: User.ID.eq(order.userID)))[0];

      List<OrderItem> orderitem = await Amplify.DataStore.query(
          OrderItem.classType,
          where: OrderItem.ORDERID.eq(order.id));

      orderitem.asMap().forEach((index, orderitem) {
        orderItemByOrderId.add({
          "order item id": orderitem.id,
          "item name": orderitem.item,
          "price": orderitem.price.toString(),
          "quantity": orderitem.quantity.toString(),
        });
      });

      fullOrderItemList.add({
        'order id': order.id,
        'order date': order.orderDate,
        'total price': order.totalPrice.toString(),
        'buyer name': buyerInfo.name,
        'buyer phone': buyerInfo.phone,
        'buyer email': buyerInfo.email,
        'order item': orderItemByOrderId,
      });
    });
    setState(() {
      _orderList = fullOrderItemList;
    });
  }
giselle99
  • 21
  • 1

1 Answers1

0

You should use await with _fetchOrder().

One way to get around this would be to make _fetchOrder() return the fullOrderItemList and use setState inside Future.then:


  @override
  void initState() {
    super.initState();
    _subscription =
        Amplify.DataStore.observe(OrderItem.classType).listen((event) {
      _fetchOrder().then((orderList) => setState(() {
         _orderList = orderList;
      });
    });
    _orderList = [];
    _fetchOrder().then((orderList) => setState(() {
       _orderList = orderList;
    });
  }

If this doesn't work, you can try this:


_fetchOrder().then((orderList) {
  WidgetsBinding.instance!.addPostFrameCallback((_) => setState(() {
    _orderList = orderList;
  })}
);


Eric Omine
  • 489
  • 4
  • 15
  • Hi! Thanks for your answer. I tried but both doesn't work for me :( – giselle99 Jun 04 '22 at 15:57
  • @giselle99 that's weird. I'd suggest you to put one breakpoint inside the build method and another inside the setState call, to make sure the build is called with the data inside build after you called setState. It'd be a first step. – Eric Omine Jun 04 '22 at 20:19