flutterfirebasegoogle-cloud-firestoreprovider

how to pass Data to the UI


this is what I'm trying to build here is the code

class LogisticsPageScreen extends StatefulWidget {
  @override
  _LogisticsPageScreenState createState() => _LogisticsPageScreenState();
}

class _LogisticsPageScreenState extends State<LogisticsPageScreen> {
  List<LogisticsData> logisticsData = [];

  @override
  void initState() {
    super.initState();
    fetchLogisticsData();
  }

  Future<void> fetchLogisticsData() async {
    try {
      QuerySnapshot querySnapshot =
          await FirebaseFirestore.instance.collection('allocations').get();

      List<LogisticsData> tempData = querySnapshot.docs.map((doc) {
        print("Document data: ${doc.data()}"); // Debug log for document data
        return LogisticsData(
          eventName: doc['event'] ?? 'N/A',
          driver: doc['driver'] ?? 'N/A',
          guide: doc['guide'] ?? 'N/A',
        );
      }).toList();

      setState(() {
        logisticsData = tempData;
        // Print the fetched logistics data
        print("Fetched logistics data: $logisticsData");
      });
      print(
          "Logistics data loaded successfully"); // Debug log for successful data load
    } catch (e) {
      // Handle any errors that might occur
      print("Error fetching logistics data: $e"); // Debug log for error
    }
  }

  @override
  Widget build(BuildContext context) {
    return LogisticsPage(logisticsData: logisticsData);
  }
}

I tried to use future builder, to achive another way of passing data to the UI but it was not efefctive.. What might the problem that deters passing of data to the UI. From the console there's data there but on the UI its not appearing.


Solution

  • When the LogisticsPageScreen widget is initially built, logisticsData is empty. At this point, the fetchLogisticsData function is triggered in initState to asynchronously fetch data from Firestore. However, since fetchLogisticsData is asynchronous, it doesn't block the widget from being built initially with logisticsData being empty.

    To handle this scenario, you should ensure that the UI updates after logisticsData has been populated with data from Firestore. The setState method, which you already use within fetchLogisticsData, triggers a rebuild of the widget when logisticsData changes. Here’s how you can structure your widget to handle the asynchronous data fetching properly:

    class LogisticsPageScreen extends StatefulWidget {
      const LogisticsPageScreen({super.key});
    
      @override
      State<LogisticsPageScreen> createState() => _LogisticsPageScreenState();
    }
    
    class _LogisticsPageScreenState extends State<LogisticsPageScreen> {
      Future<List<LogisticsData>> futureLogisticsData;
    
      @override
      void initState() {
        super.initState();
        futureLogisticsData = fetchLogisticsData();
      }
    
      Future<List<LogisticsData>> fetchLogisticsData() async {
        try {
          QuerySnapshot querySnapshot =
              await FirebaseFirestore.instance.collection('allocations').get();
    
          List<LogisticsData> tempData = querySnapshot.docs.map((doc) {
            return LogisticsData(
              eventName: doc['event'] ?? 'N/A',
              driver: doc['driver'] ?? 'N/A',
              guide: doc['guide'] ?? 'N/A',
            );
          }).toList();
          return tempData;
        } catch (e) {
          return []; 
        }
      }
    
    
      @override
      Widget build(BuildContext context) {
        return FutureBuilder<List<LogisticsData>>(
          future: futureLogisticsData,
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return Center(child: CircularProgressIndicator());
            } else if (snapshot.hasError) {
              return Center(child: Text('Error: ${snapshot.error}'));
            } else if (!snapshot.hasData || snapshot.data.isEmpty) {
              return Center(child: Text('No data available'));
            } else {
              return LogisticsPage(logisticsData: snapshot.data);
            }
          },
        );
      }
    }