skip to Main Content

I am able to do a get query into firebase and use the print function to confirm it is working. However I don’t understand how to access the retrieved variable elsewhere in the code. I am getting an error "Error: The getter ‘data’ isn’t defined for the class ‘ItemDetails’" for the attempted text field below. Please could someone point me in the right direction? Thanks

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';

class ItemDetails extends StatelessWidget {
  ItemDetails(this.itemId, {Key? key}) : super(key: key) {

        var db = FirebaseFirestore.instance;

        final docRef = db.collection("collection_name").doc("frngqy6aaxb88mw2n09p6e9qhkrkhhmmywrahm8f79e4myuwku6");

        docRef.get().then(
              (DocumentSnapshot doc) {
            final data = doc.data() as Map<String, dynamic>;
            print(data["name"]);  // !!! THIS WORKS !!!
            return data;
          },
          onError: (e) => print("Error getting document: $e"),

        );

  }

  String itemId;

  late DocumentReference _reference;

  @override
  Widget build(BuildContext context) {

    return Scaffold(

      appBar: AppBar(
        title: Text("Item detail"),
      ),
        body: Center(
            child: Text(data["name"])     // !!! THIS LINE GIVES THE ERROR !!!
        )
    );
  }
}

I tried adding the "return data;" line but it didn’t help

2

Answers


  1. In your current code, you are trying to access the data variable outside the then callback, which leads to the error you mentioned. The then callback is asynchronous, and its execution may not have been completed by the time the build method is called.

    To handle asynchronous operations and update the UI with the retrieved data, you should use the FutureBuilder widget

    import 'package:cloud_firestore/cloud_firestore.dart';
    import 'package:flutter/material.dart';
    
    class ItemDetails extends StatelessWidget {
      final String itemId;
    
      ItemDetails(this.itemId, {Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        final DocumentReference docRef = FirebaseFirestore.instance.collection("collection_name").doc("frngqy6aaxb88mw2n09p6e9qhkrkhhmmywrahm8f79e4myuwku6");
    
        return Scaffold(
          appBar: AppBar(
            title: Text("Item detail"),
          ),
          body: FutureBuilder<DocumentSnapshot>(
            future: docRef.get(),
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.waiting) {
                return Center(
                  child: CircularProgressIndicator(),
                );
              } else if (snapshot.hasError) {
                return Center(
                  child: Text("Error: ${snapshot.error}"),
                );
              } else {
                final data = snapshot.data!.data() as Map<String, dynamic>;
                return Center(
                  child: Text(data["name"]),
                );
              }
            },
          ),
        );
      }
    }
    
    Login or Signup to reply.
  2. If the operations you’re going to perform are asynchronous, you can convert them into a Future to manage them more easily. After converting them into Future, you can prepare the UI part where you will display the data by calling it in the desired page as FutureBuilder. I’ve implemented it for you in the example below. I hope it helps you 🙂

    import 'package:cloud_firestore/cloud_firestore.dart';
    import 'package:flutter/material.dart';
    
    class ItemDetails extends StatelessWidget {
      const ItemDetails({
        Key? key,
        required this.itemId,
      }) : super(key: key);
    
      final String itemId;
    
      Future<Map<String, dynamic>> getData() async {
        var db = FirebaseFirestore.instance;
        Map<String, dynamic> data;
        final docRef = db
            .collection("collection_name")
            .doc("frngqy6aaxb88mw2n09p6e9qhkrkhhmmywrahm8f79e4myuwku6");
        return docRef.get().then((value) {
          data = value.data() as Map<String, dynamic>;
          return data;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text("Item detail"),
          ),
          body: Center(
            child: FutureBuilder<Map<String, dynamic>>(
              future: getData(),
              builder: (context, snapshot) {
                if (snapshot.hasData) {
                  final data = snapshot.data!;
                  // !!! YOU CAN MANAGE YOUR DATA HERE !!!
                  return Text(data["name"]);
                } else if (snapshot.connectionState == ConnectionState.waiting) {
                  // !!! IF YOU WANT TO SHOW A LOADING SCREEN !!!
                  return const CircularProgressIndicator();
                } else {
                  // !!! IF YOU WANT TO SHOW AN ERROR SCREEN !!!
                  return const Text("Error");
                }
              },
            ),
          ),
        );
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search