Search code examples
flutterdartflutter-providerstatefulwidget

How can I rebuild a page after setting its state with Providers?


I'm new to Providers and I was enjoying how relatively fast and simple it was.
However, I've encountered an issue with the app I'm currently building.
It's a simple app that fetches items, the user and his/her cart.

Displaying the user's info, cart and fetching items works just fine. The issue is when I want to add an item to the cart: I successfully add it to the database but the UI doesn't change. The UI updates after a full restart of the app

Cart Page

import 'package:coolkicks/providers/user-provider.dart';
import 'package:coolkicks/shared/cartItems.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class Cart extends StatefulWidget {
  @override
  _CartState createState() => _CartState();
}

class _CartState extends State<Cart> {

   @override
 void didChangeDependencies() {
    super.didChangeDependencies();
    
    Future.delayed(Duration.zero, () {
      Provider.of<UserProvider>(context, listen: false).fetchTheUser();
   });  
   
  }

  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: <Widget>[],
        title: Text('Cart'),
      ),
      body: 
      Consumer<UserProvider>(
        builder: (context, model, child) {
          if (model.isLoading) {
            return Center(child: CircularProgressIndicator());
          } else {
            return CartItems();
          }
        },
      ),
    );
  }
}

Add to Cart Page

import 'package:coolkicks/models/product.dart';
import 'package:coolkicks/providers/product-provider.dart';
import 'package:coolkicks/providers/user-provider.dart';
import 'package:coolkicks/screens/cart.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class DetailsPage extends StatefulWidget {
  final Product product;
  DetailsPage({this.product});

  @override
  _DetailsPageState createState() => _DetailsPageState();
}

class _DetailsPageState extends State<DetailsPage> {
  bool loading = false;
  @override
  Widget build(BuildContext context) {
    final Map<String, dynamic> user =
        Provider.of<UserProvider>(context, listen: false).user;
    Map<String, String> data;
    if (user != null) {
      data = {
        "shoeId": widget.product.shoeId,
        "shoeSize": "32",
        "email": user['user'].email
      };
    }

    return Scaffold(
        backgroundColor: Colors.blue[100],
        appBar: AppBar(
          elevation: 0.0,
          title: Text('Details'),
        ),
        body: Column(
          children: <Widget>[
            Card(
              margin: EdgeInsets.fromLTRB(20.0, 6.0, 20.0, 0.0),
              child: ListTile(
                trailing: Text('Ksh. ${widget.product.price.toString()}'),
                leading: CircleAvatar(
                    radius: 25.0,
                    backgroundImage: AssetImage('assets/shoe.jpg')),
                title: Text(widget.product.title),
                subtitle: Text(widget.product.description),
              ),
            ),
            SizedBox(height: 50.0),
            Consumer<ProductProvider>(builder: (context, model, child) {
              return  loading ? CircularProgressIndicator() :  RaisedButton(
                  child: Text('Add to Cart'),
                  onPressed: () async {
                     setState(() {
                              loading = true;
                            });
                    if (user == null) {
                      return print('Login to add to cart');
                    } else {
                      return model.addToCart(data)
                          .then((value) => {
                                setState(() {
                              loading = false;
                            }),
                                Navigator.push(
                                    context,
                                    CupertinoPageRoute(
                                        builder: (context) => Cart()))
                              })
                          .catchError((err) {
                        print(err);
                      });
                    }
                  });
            })
          ],
        ));
  }
}

How can I make it that everytime the Cart Page is rendered, the data is fetched from the database?


Solution

  • I figured out the problem.
    It was rather a silly one In my UserProvider, when fetching the cart, I wasn't catering for the user not being empty. After commenting out the if check, it worked. I'll have to rethink my way of checking for the user

     Future fetchTheUser() async {
        final Map<String, User> fetchedUser = {};
        final List<Cart> fetchedCart = [];
    
        // if (_user.isEmpty) {
          _isLoading = true;
          notifyListeners();
          final Map<String, dynamic> userData =
              await getProfile().catchError((error) => {_isLoading = true});
    
          if (userData == null) {
            return _user = null;
          } else {
            final theUser = User(
                firstname: userData['firstname'],
                lastname: userData['lastname'],
                email: userData['email'],
                cart: userData['cart']);
            fetchedUser['user'] = theUser;
            _user = fetchedUser;
    
           
            
            final Map<String, dynamic> cartData = userData['cart'];
            
            cartData['items'].forEach((dynamic cartItem) {
              final Cart cart = Cart(
                productId: cartItem['productId'],
                  item: cartItem['item'],
                  qty: cartItem['qty'],
                  price: cartItem['price'],
                  totalPrice: cartData['totalPrice'],
                  totalQty: cartData['totalQty']
                  );
    
              fetchedCart.add(cart);
            });
            _cart = fetchedCart;
            _isLoading = false;
            notifyListeners();
          }
        // } else {
          
        //   _user = _user;
        //   notifyListeners();
        // }
      }