skip to Main Content

I need to retrieve the document id of a newly created Firebase document but I am having trouble doing this.

I send the client data in a notifier provider to a save Firestore save function. The document is created and the data is saved successfully. I don’t get an error in the process.

After the document is created and the data saved, I return the document id in the variable, id.

However, in the execution and watching the process in the debugger, the return statement is not executed and the execution is returned to a completely different place in the code.

Here is where I start the "save" process by a statement in the clientNotifierProvider:

 String? clientId = await firestoreService.saveNewClient(toMap(newClient));
      if (clientId != null) {
        ref.read(clientNotifierProvider.notifier).updateClientId(clientId);
      }

Here the save is initiated and the execution should be returned to the if statement but this code is skipped and I don’t know why.

this is the Firestore save method I use to create the document and capture the document id. The document is saved correctly but the return statement is skipped and there is no error thrown.
This is the code below:

  Future<String?> saveNewClient(client) async {
    // Get the document ID of the new document so it can be
    // added to the new transaction document.
    try {
      /// You can generate a document id before the create operate
      String id = _db.collection("client").doc().id;

      /// pass the generated id to the doc reference and set it
      /// .toMap() -> Assuming your client isn't of type map
      await _db.collection('client').doc(id).set(client);
      //DocumentReference refDoc = await _db.collection('client').add(client);

      /// upon success return the id
      return id;
    } catch (e) {
      print(e);

      /// or return null if the operation failed
      return null;
    }
  }

Why is this code being skipped? The variable "id" contains the new document id so why am I not able to return this id to the calling statement?
Thanks

UPDATE:
I changed the calling code to this but there is no change. I still do not get the documented back:

firestoreService.saveNewClient(toMap(newClient)).then((String? clientId) {
    if (clientId != null) {
      ref.read(clientNotifierProvider.notifier).updateClientId(clientId);
    }
    return null;
  });

UPDATE 2:
I tried the fix suggested but I am getting an error. Here is the new code:

      firestoreService
          .saveNewClient(toMap(newClient))
          .then((DocumentReference? docRef) {
        ref.read(clientNotifierProvider.notifier).updateClientId(docRef!.id);
      });

  Future<DocumentReference?> saveNewClient(client) async {
    try {
      DocumentReference docRef =
          await _db.collection('client').add(client).then(
        (docRef) {
          return docRef;
        },
      );
    } catch (e) {
      return null;
    }
  }

docRef.Id has a value inside the saveNewClient function but when I return to the calling code, docRef is null.

Why is this null and how do I fix this?
Thanks

2

Answers


  1. Please use below code for your issue

    Future<void> createDocument() async {
        // Instance of firestore 
        FirebaseFirestore firestore = FirebaseFirestore.instance;
        
        DocumentReference docRef =
         await firestore.collection('YOUR_COLLECTION_NAME').add(YOUR_MAP)
        .then(
           (docRef) {
             print('${docRef.id}');
             // Enter your Update doc code
          },
        );
    }
    
    Login or Signup to reply.
  2. Your saveNewClient function attempts to return a DocumentReference, but there’s a mistake in the try block’s scope regarding the return statement. The return statement is placed within a lambda function passed to .then(), which does not actually return from saveNewClient but from the lambda itself. This leads to your function not returning anything explicitly, hence the null.

    You should directly return the DocumentReference obtained from the .add() method without using .then(), ensuring the function properly returns the expected value.

    Future<String?> saveNewClient(Map<String, dynamic> client) async {
      try {
        // Directly add the new client to Firestore, which returns a DocumentReference
        DocumentReference docRef = await _db.collection('client').add(client);
    
        // Return the document ID
        return docRef.id;
      } catch (e) {
        print(e);
        // Return null if there's an error
        return null;
      }
    }
    

    With the corrected saveNewClient function, you can now await its result directly or use .then() if you prefer the Future-based approach.

    // Using async-await syntax
    try {
      String? clientId = await firestoreService.saveNewClient(toMap(newClient));
      if (clientId != null) {
        ref.read(clientNotifierProvider.notifier).updateClientId(clientId);
      }
    } catch (e) {
      // Handle any errors here
      print(e);
    }
    
    // using the Future-based approach with `.then()`
    firestoreService.saveNewClient(toMap(newClient)).then((clientId) {
      if (clientId != null) {
        ref.read(clientNotifierProvider.notifier).updateClientId(clientId);
      }
    }).catchError((e) {
      // Handle any errors here
      print(e);
    });
    

    Note:
    In your original attempt, you were directly setting a document with a specific ID, which is a valid approach if you need to control the document IDs or reuse them later. I have used .add(), which automatically generates a document ID.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search